1// 2// Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. 3// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4// 5// This code is free software; you can redistribute it and/or modify it 6// under the terms of the GNU General Public License version 2 only, as 7// published by the Free Software Foundation. 8// 9// This code is distributed in the hope that it will be useful, but WITHOUT 10// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12// version 2 for more details (a copy is included in the LICENSE file that 13// accompanied this code). 14// 15// You should have received a copy of the GNU General Public License version 16// 2 along with this work; if not, write to the Free Software Foundation, 17// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18// 19// Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20// or visit www.oracle.com if you need additional information or have any 21// questions. 22// 23 24// ARM Architecture Description File 25 26//----------DEFINITION BLOCK--------------------------------------------------- 27// Define name --> value mappings to inform the ADLC of an integer valued name 28// Current support includes integer values in the range [0, 0x7FFFFFFF] 29// Format: 30// int_def <name> ( <int_value>, <expression>); 31// Generated Code in ad_<arch>.hpp 32// #define <name> (<expression>) 33// // value == <int_value> 34// Generated code in ad_<arch>.cpp adlc_verification() 35// assert( <name> == <int_value>, "Expect (<expression>) to equal <int_value>"); 36// 37definitions %{ 38// The default cost (of an ALU instruction). 39 int_def DEFAULT_COST ( 100, 100); 40 int_def HUGE_COST (1000000, 1000000); 41 42// Memory refs are twice as expensive as run-of-the-mill. 43 int_def MEMORY_REF_COST ( 200, DEFAULT_COST * 2); 44 45// Branches are even more expensive. 46 int_def BRANCH_COST ( 300, DEFAULT_COST * 3); 47 int_def CALL_COST ( 300, DEFAULT_COST * 3); 48%} 49 50 51//----------SOURCE BLOCK------------------------------------------------------- 52// This is a block of C++ code which provides values, functions, and 53// definitions necessary in the rest of the architecture description 54source_hpp %{ 55// Header information of the source block. 56// Method declarations/definitions which are used outside 57// the ad-scope can conveniently be defined here. 58// 59// To keep related declarations/definitions/uses close together, 60// we switch between source %{ }% and source_hpp %{ }% freely as needed. 61 62// Does destination need to be loaded in a register then passed to a 63// branch instruction? 64extern bool maybe_far_call(const CallNode *n); 65extern bool maybe_far_call(const MachCallNode *n); 66static inline bool cache_reachable() { 67 return MacroAssembler::_cache_fully_reachable(); 68} 69 70#define ldr_32 ldr 71#define str_32 str 72#define tst_32 tst 73#define teq_32 teq 74#if 1 75extern bool PrintOptoAssembly; 76#endif 77 78class c2 { 79public: 80 static OptoRegPair return_value(int ideal_reg); 81}; 82 83class 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 101class 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 119class Node::PD { 120public: 121 enum NodeFlags { 122 _last_flag = Node::_last_flag 123 }; 124}; 125 126%} 127 128source %{ 129#define __ _masm. 130 131static FloatRegister reg_to_FloatRegister_object(int register_encoding); 132static Register reg_to_register_object(int register_encoding); 133 134void PhaseOutput::pd_perform_mach_node_analysis() { 135} 136 137int MachNode::pd_alignment_required() const { 138 return 1; 139} 140 141int MachNode::compute_padding(int current_offset) const { 142 return 0; 143} 144 145// **************************************************************************** 146 147// REQUIRED FUNCTIONALITY 148 149// emit an interrupt that is caught by the debugger (for debugging compiler) 150void emit_break(CodeBuffer &cbuf) { 151 C2_MacroAssembler _masm(&cbuf); 152 __ breakpoint(); 153} 154 155#ifndef PRODUCT 156void MachBreakpointNode::format( PhaseRegAlloc *, outputStream *st ) const { 157 st->print("TA"); 158} 159#endif 160 161void MachBreakpointNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { 162 emit_break(cbuf); 163} 164 165uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const { 166 return MachNode::size(ra_); 167} 168 169 170void emit_nop(CodeBuffer &cbuf) { 171 C2_MacroAssembler _masm(&cbuf); 172 __ nop(); 173} 174 175 176void emit_call_reloc(CodeBuffer &cbuf, const MachCallNode *n, MachOper *m, RelocationHolder const& rspec) { 177 int ret_addr_offset0 = n->as_MachCall()->ret_addr_offset(); 178 int call_site_offset = cbuf.insts()->mark_off(); 179 C2_MacroAssembler _masm(&cbuf); 180 __ set_inst_mark(); // needed in emit_to_interp_stub() to locate the call 181 address target = (address)m->method(); 182 assert(n->as_MachCall()->entry_point() == target, "sanity"); 183 assert(maybe_far_call(n) == !__ reachable_from_cache(target), "sanity"); 184 assert(cache_reachable() == __ cache_fully_reachable(), "sanity"); 185 186 assert(target != NULL, "need real address"); 187 188 int ret_addr_offset = -1; 189 if (rspec.type() == relocInfo::runtime_call_type) { 190 __ call(target, rspec); 191 ret_addr_offset = __ offset(); 192 } else { 193 // scratches Rtemp 194 ret_addr_offset = __ patchable_call(target, rspec, true); 195 } 196 assert(ret_addr_offset - call_site_offset == ret_addr_offset0, "fix ret_addr_offset()"); 197} 198 199//============================================================================= 200// REQUIRED FUNCTIONALITY for encoding 201void emit_lo(CodeBuffer &cbuf, int val) { } 202void emit_hi(CodeBuffer &cbuf, int val) { } 203 204 205//============================================================================= 206const RegMask& MachConstantBaseNode::_out_RegMask = PTR_REG_mask(); 207 208int ConstantTable::calculate_table_base_offset() const { 209 int offset = -(size() / 2); 210 // flds, fldd: 8-bit offset multiplied by 4: +/- 1024 211 // ldr, ldrb : 12-bit offset: +/- 4096 212 if (!Assembler::is_simm10(offset)) { 213 offset = Assembler::min_simm10; 214 } 215 return offset; 216} 217 218bool MachConstantBaseNode::requires_postalloc_expand() const { return false; } 219void MachConstantBaseNode::postalloc_expand(GrowableArray <Node *> *nodes, PhaseRegAlloc *ra_) { 220 ShouldNotReachHere(); 221} 222 223void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const { 224 Compile* C = ra_->C; 225 ConstantTable& constant_table = C->output()->constant_table(); 226 C2_MacroAssembler _masm(&cbuf); 227 228 Register r = as_Register(ra_->get_encode(this)); 229 CodeSection* consts_section = __ code()->consts(); 230 int consts_size = consts_section->align_at_start(consts_section->size()); 231 assert(constant_table.size() == consts_size, "must be: %d == %d", constant_table.size(), consts_size); 232 233 // Materialize the constant table base. 234 address baseaddr = consts_section->start() + -(constant_table.table_base_offset()); 235 RelocationHolder rspec = internal_word_Relocation::spec(baseaddr); 236 __ mov_address(r, baseaddr, rspec); 237} 238 239uint MachConstantBaseNode::size(PhaseRegAlloc*) const { 240 return 8; 241} 242 243#ifndef PRODUCT 244void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const { 245 char reg[128]; 246 ra_->dump_register(this, reg); 247 st->print("MOV_SLOW &constanttable,%s\t! constant table base", reg); 248} 249#endif 250 251#ifndef PRODUCT 252void MachPrologNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { 253 Compile* C = ra_->C; 254 255 for (int i = 0; i < OptoPrologueNops; i++) { 256 st->print_cr("NOP"); st->print("\t"); 257 } 258 259 size_t framesize = C->output()->frame_size_in_bytes(); 260 assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); 261 int bangsize = C->output()->bang_size_in_bytes(); 262 // Remove two words for return addr and rbp, 263 framesize -= 2*wordSize; 264 bangsize -= 2*wordSize; 265 266 // Calls to C2R adapters often do not accept exceptional returns. 267 // We require that their callers must bang for them. But be careful, because 268 // some VM calls (such as call site linkage) can use several kilobytes of 269 // stack. But the stack safety zone should account for that. 270 // See bugs 4446381, 4468289, 4497237. 271 if (C->output()->need_stack_bang(bangsize)) { 272 st->print_cr("! stack bang (%d bytes)", bangsize); st->print("\t"); 273 } 274 st->print_cr("PUSH R_FP|R_LR_LR"); st->print("\t"); 275 if (framesize != 0) { 276 st->print ("SUB R_SP, R_SP, " SIZE_FORMAT,framesize); 277 } 278} 279#endif 280 281void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { 282 Compile* C = ra_->C; 283 C2_MacroAssembler _masm(&cbuf); 284 285 for (int i = 0; i < OptoPrologueNops; i++) { 286 __ nop(); 287 } 288 289 size_t framesize = C->output()->frame_size_in_bytes(); 290 assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); 291 int bangsize = C->output()->bang_size_in_bytes(); 292 // Remove two words for return addr and fp, 293 framesize -= 2*wordSize; 294 bangsize -= 2*wordSize; 295 296 // Calls to C2R adapters often do not accept exceptional returns. 297 // We require that their callers must bang for them. But be careful, because 298 // some VM calls (such as call site linkage) can use several kilobytes of 299 // stack. But the stack safety zone should account for that. 300 // See bugs 4446381, 4468289, 4497237. 301 if (C->output()->need_stack_bang(bangsize)) { 302 __ arm_stack_overflow_check(bangsize, Rtemp); 303 } 304 305 __ raw_push(FP, LR); 306 if (framesize != 0) { 307 __ sub_slow(SP, SP, framesize); 308 } 309 310 // offset from scratch buffer is not valid 311 if (strcmp(cbuf.name(), "Compile::Fill_buffer") == 0) { 312 C->output()->set_frame_complete( __ offset() ); 313 } 314 315 if (C->has_mach_constant_base_node()) { 316 // NOTE: We set the table base offset here because users might be 317 // emitted before MachConstantBaseNode. 318 ConstantTable& constant_table = C->output()->constant_table(); 319 constant_table.set_table_base_offset(constant_table.calculate_table_base_offset()); 320 } 321} 322 323uint MachPrologNode::size(PhaseRegAlloc *ra_) const { 324 return MachNode::size(ra_); 325} 326 327int MachPrologNode::reloc() const { 328 return 10; // a large enough number 329} 330 331//============================================================================= 332#ifndef PRODUCT 333void MachEpilogNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { 334 Compile* C = ra_->C; 335 336 size_t framesize = C->output()->frame_size_in_bytes(); 337 framesize -= 2*wordSize; 338 339 if (framesize != 0) { 340 st->print("ADD R_SP, R_SP, " SIZE_FORMAT "\n\t",framesize); 341 } 342 st->print("POP R_FP|R_LR_LR"); 343 344 if (do_polling() && ra_->C->is_method_compilation()) { 345 st->print("\n\t"); 346 st->print("MOV Rtemp, #PollAddr\t! Load Polling address\n\t"); 347 st->print("LDR Rtemp,[Rtemp]\t!Poll for Safepointing"); 348 } 349} 350#endif 351 352void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { 353 C2_MacroAssembler _masm(&cbuf); 354 Compile* C = ra_->C; 355 356 size_t framesize = C->output()->frame_size_in_bytes(); 357 framesize -= 2*wordSize; 358 if (framesize != 0) { 359 __ add_slow(SP, SP, framesize); 360 } 361 __ raw_pop(FP, LR); 362 363 // If this does safepoint polling, then do it here 364 if (do_polling() && ra_->C->is_method_compilation()) { 365 __ read_polling_page(Rtemp, relocInfo::poll_return_type); 366 } 367} 368 369uint MachEpilogNode::size(PhaseRegAlloc *ra_) const { 370 return MachNode::size(ra_); 371} 372 373int MachEpilogNode::reloc() const { 374 return 16; // a large enough number 375} 376 377const Pipeline * MachEpilogNode::pipeline() const { 378 return MachNode::pipeline_class(); 379} 380 381//============================================================================= 382 383// Figure out which register class each belongs in: rc_int, rc_float, rc_stack 384enum RC { rc_bad, rc_int, rc_float, rc_stack }; 385static enum RC rc_class( OptoReg::Name reg ) { 386 if (!OptoReg::is_valid(reg)) return rc_bad; 387 if (OptoReg::is_stack(reg)) return rc_stack; 388 VMReg r = OptoReg::as_VMReg(reg); 389 if (r->is_Register()) return rc_int; 390 assert(r->is_FloatRegister(), "must be"); 391 return rc_float; 392} 393 394static inline bool is_iRegLd_memhd(OptoReg::Name src_first, OptoReg::Name src_second, int offset) { 395 int rlo = Matcher::_regEncode[src_first]; 396 int rhi = Matcher::_regEncode[src_second]; 397 if (!((rlo&1)==0 && (rlo+1 == rhi))) { 398 tty->print_cr("CAUGHT BAD LDRD/STRD"); 399 } 400 return (rlo&1)==0 && (rlo+1 == rhi) && is_memoryHD(offset); 401} 402 403uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, 404 PhaseRegAlloc *ra_, 405 bool do_size, 406 outputStream* st ) const { 407 // Get registers to move 408 OptoReg::Name src_second = ra_->get_reg_second(in(1)); 409 OptoReg::Name src_first = ra_->get_reg_first(in(1)); 410 OptoReg::Name dst_second = ra_->get_reg_second(this ); 411 OptoReg::Name dst_first = ra_->get_reg_first(this ); 412 413 enum RC src_second_rc = rc_class(src_second); 414 enum RC src_first_rc = rc_class(src_first); 415 enum RC dst_second_rc = rc_class(dst_second); 416 enum RC dst_first_rc = rc_class(dst_first); 417 418 assert( OptoReg::is_valid(src_first) && OptoReg::is_valid(dst_first), "must move at least 1 register" ); 419 420 // Generate spill code! 421 int size = 0; 422 423 if (src_first == dst_first && src_second == dst_second) 424 return size; // Self copy, no move 425 426#ifdef TODO 427 if (bottom_type()->isa_vect() != NULL) { 428 } 429#endif 430 431 // Shared code does not expect instruction set capability based bailouts here. 432 // Handle offset unreachable bailout with minimal change in shared code. 433 // Bailout only for real instruction emit. 434 // This requires a single comment change in shared code. ( see output.cpp "Normal" instruction case ) 435 436 C2_MacroAssembler _masm(cbuf); 437 438 // -------------------------------------- 439 // Check for mem-mem move. Load into unused float registers and fall into 440 // the float-store case. 441 if (src_first_rc == rc_stack && dst_first_rc == rc_stack) { 442 int offset = ra_->reg2offset(src_first); 443 if (cbuf && !is_memoryfp(offset)) { 444 ra_->C->record_method_not_compilable("unable to handle large constant offsets"); 445 return 0; 446 } else { 447 if (src_second_rc != rc_bad) { 448 assert((src_first&1)==0 && src_first+1 == src_second, "pair of registers must be aligned/contiguous"); 449 src_first = OptoReg::Name(R_mem_copy_lo_num); 450 src_second = OptoReg::Name(R_mem_copy_hi_num); 451 src_first_rc = rc_float; 452 src_second_rc = rc_float; 453 if (cbuf) { 454 __ ldr_double(Rmemcopy, Address(SP, offset)); 455 } else if (!do_size) { 456 st->print(LDR_DOUBLE " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first),offset); 457 } 458 } else { 459 src_first = OptoReg::Name(R_mem_copy_lo_num); 460 src_first_rc = rc_float; 461 if (cbuf) { 462 __ ldr_float(Rmemcopy, Address(SP, offset)); 463 } else if (!do_size) { 464 st->print(LDR_FLOAT " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first),offset); 465 } 466 } 467 size += 4; 468 } 469 } 470 471 if (src_second_rc == rc_stack && dst_second_rc == rc_stack) { 472 Unimplemented(); 473 } 474 475 // -------------------------------------- 476 // Check for integer reg-reg copy 477 if (src_first_rc == rc_int && dst_first_rc == rc_int) { 478 // Else normal reg-reg copy 479 assert( src_second != dst_first, "smashed second before evacuating it" ); 480 if (cbuf) { 481 __ mov(reg_to_register_object(Matcher::_regEncode[dst_first]), reg_to_register_object(Matcher::_regEncode[src_first])); 482#ifndef PRODUCT 483 } else if (!do_size) { 484 st->print("MOV R_%s, R_%s\t# spill", 485 Matcher::regName[dst_first], 486 Matcher::regName[src_first]); 487#endif 488 } 489 size += 4; 490 } 491 492 // Check for integer store 493 if (src_first_rc == rc_int && dst_first_rc == rc_stack) { 494 int offset = ra_->reg2offset(dst_first); 495 if (cbuf && !is_memoryI(offset)) { 496 ra_->C->record_method_not_compilable("unable to handle large constant offsets"); 497 return 0; 498 } else { 499 if (src_second_rc != rc_bad && is_iRegLd_memhd(src_first, src_second, offset)) { 500 assert((src_first&1)==0 && src_first+1 == src_second, "pair of registers must be aligned/contiguous"); 501 if (cbuf) { 502 __ str_64(reg_to_register_object(Matcher::_regEncode[src_first]), Address(SP, offset)); 503#ifndef PRODUCT 504 } else if (!do_size) { 505 if (size != 0) st->print("\n\t"); 506 st->print(STR_64 " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first), offset); 507#endif 508 } 509 return size + 4; 510 } else { 511 if (cbuf) { 512 __ str_32(reg_to_register_object(Matcher::_regEncode[src_first]), Address(SP, offset)); 513#ifndef PRODUCT 514 } else if (!do_size) { 515 if (size != 0) st->print("\n\t"); 516 st->print(STR_32 " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first), offset); 517#endif 518 } 519 } 520 } 521 size += 4; 522 } 523 524 // Check for integer load 525 if (dst_first_rc == rc_int && src_first_rc == rc_stack) { 526 int offset = ra_->reg2offset(src_first); 527 if (cbuf && !is_memoryI(offset)) { 528 ra_->C->record_method_not_compilable("unable to handle large constant offsets"); 529 return 0; 530 } else { 531 if (src_second_rc != rc_bad && is_iRegLd_memhd(dst_first, dst_second, offset)) { 532 assert((src_first&1)==0 && src_first+1 == src_second, "pair of registers must be aligned/contiguous"); 533 if (cbuf) { 534 __ ldr_64(reg_to_register_object(Matcher::_regEncode[dst_first]), Address(SP, offset)); 535#ifndef PRODUCT 536 } else if (!do_size) { 537 if (size != 0) st->print("\n\t"); 538 st->print(LDR_64 " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_first), offset); 539#endif 540 } 541 return size + 4; 542 } else { 543 if (cbuf) { 544 __ ldr_32(reg_to_register_object(Matcher::_regEncode[dst_first]), Address(SP, offset)); 545#ifndef PRODUCT 546 } else if (!do_size) { 547 if (size != 0) st->print("\n\t"); 548 st->print(LDR_32 " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_first), offset); 549#endif 550 } 551 } 552 } 553 size += 4; 554 } 555 556 // Check for float reg-reg copy 557 if (src_first_rc == rc_float && dst_first_rc == rc_float) { 558 if (src_second_rc != rc_bad) { 559 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"); 560 if (cbuf) { 561 __ mov_double(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), reg_to_FloatRegister_object(Matcher::_regEncode[src_first])); 562#ifndef PRODUCT 563 } else if (!do_size) { 564 st->print(MOV_DOUBLE " R_%s, R_%s\t# spill", 565 Matcher::regName[dst_first], 566 Matcher::regName[src_first]); 567#endif 568 } 569 return 4; 570 } 571 if (cbuf) { 572 __ mov_float(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), reg_to_FloatRegister_object(Matcher::_regEncode[src_first])); 573#ifndef PRODUCT 574 } else if (!do_size) { 575 st->print(MOV_FLOAT " R_%s, R_%s\t# spill", 576 Matcher::regName[dst_first], 577 Matcher::regName[src_first]); 578#endif 579 } 580 size = 4; 581 } 582 583 // Check for float store 584 if (src_first_rc == rc_float && dst_first_rc == rc_stack) { 585 int offset = ra_->reg2offset(dst_first); 586 if (cbuf && !is_memoryfp(offset)) { 587 ra_->C->record_method_not_compilable("unable to handle large constant offsets"); 588 return 0; 589 } else { 590 // Further check for aligned-adjacent pair, so we can use a double store 591 if (src_second_rc != rc_bad) { 592 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"); 593 if (cbuf) { 594 __ str_double(reg_to_FloatRegister_object(Matcher::_regEncode[src_first]), Address(SP, offset)); 595#ifndef PRODUCT 596 } else if (!do_size) { 597 if (size != 0) st->print("\n\t"); 598 st->print(STR_DOUBLE " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first),offset); 599#endif 600 } 601 return size + 4; 602 } else { 603 if (cbuf) { 604 __ str_float(reg_to_FloatRegister_object(Matcher::_regEncode[src_first]), Address(SP, offset)); 605#ifndef PRODUCT 606 } else if (!do_size) { 607 if (size != 0) st->print("\n\t"); 608 st->print(STR_FLOAT " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first),offset); 609#endif 610 } 611 } 612 } 613 size += 4; 614 } 615 616 // Check for float load 617 if (dst_first_rc == rc_float && src_first_rc == rc_stack) { 618 int offset = ra_->reg2offset(src_first); 619 if (cbuf && !is_memoryfp(offset)) { 620 ra_->C->record_method_not_compilable("unable to handle large constant offsets"); 621 return 0; 622 } else { 623 // Further check for aligned-adjacent pair, so we can use a double store 624 if (src_second_rc != rc_bad) { 625 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"); 626 if (cbuf) { 627 __ ldr_double(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), Address(SP, offset)); 628#ifndef PRODUCT 629 } else if (!do_size) { 630 if (size != 0) st->print("\n\t"); 631 st->print(LDR_DOUBLE " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_first),offset); 632#endif 633 } 634 return size + 4; 635 } else { 636 if (cbuf) { 637 __ ldr_float(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), Address(SP, offset)); 638#ifndef PRODUCT 639 } else if (!do_size) { 640 if (size != 0) st->print("\n\t"); 641 st->print(LDR_FLOAT " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_first),offset); 642#endif 643 } 644 } 645 } 646 size += 4; 647 } 648 649 // check for int reg -> float reg move 650 if (src_first_rc == rc_int && dst_first_rc == rc_float) { 651 // Further check for aligned-adjacent pair, so we can use a single instruction 652 if (src_second_rc != rc_bad) { 653 assert((dst_first&1)==0 && dst_first+1 == dst_second, "pairs of registers must be aligned/contiguous"); 654 assert((src_first&1)==0 && src_first+1 == src_second, "pairs of registers must be aligned/contiguous"); 655 assert(src_second_rc == rc_int && dst_second_rc == rc_float, "unsupported"); 656 if (cbuf) { 657 __ 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])); 658#ifndef PRODUCT 659 } else if (!do_size) { 660 if (size != 0) st->print("\n\t"); 661 st->print("FMDRR R_%s, R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(src_first), OptoReg::regname(src_second)); 662#endif 663 } 664 return size + 4; 665 } else { 666 if (cbuf) { 667 __ fmsr(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), reg_to_register_object(Matcher::_regEncode[src_first])); 668#ifndef PRODUCT 669 } else if (!do_size) { 670 if (size != 0) st->print("\n\t"); 671 st->print(FMSR " R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(src_first)); 672#endif 673 } 674 size += 4; 675 } 676 } 677 678 // check for float reg -> int reg move 679 if (src_first_rc == rc_float && dst_first_rc == rc_int) { 680 // Further check for aligned-adjacent pair, so we can use a single instruction 681 if (src_second_rc != rc_bad) { 682 assert((src_first&1)==0 && src_first+1 == src_second, "pairs of registers must be aligned/contiguous"); 683 assert((dst_first&1)==0 && dst_first+1 == dst_second, "pairs of registers must be aligned/contiguous"); 684 assert(src_second_rc == rc_float && dst_second_rc == rc_int, "unsupported"); 685 if (cbuf) { 686 __ 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])); 687#ifndef PRODUCT 688 } else if (!do_size) { 689 if (size != 0) st->print("\n\t"); 690 st->print("FMRRD R_%s, R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(dst_second), OptoReg::regname(src_first)); 691#endif 692 } 693 return size + 4; 694 } else { 695 if (cbuf) { 696 __ fmrs(reg_to_register_object(Matcher::_regEncode[dst_first]), reg_to_FloatRegister_object(Matcher::_regEncode[src_first])); 697#ifndef PRODUCT 698 } else if (!do_size) { 699 if (size != 0) st->print("\n\t"); 700 st->print(FMRS " R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(src_first)); 701#endif 702 } 703 size += 4; 704 } 705 } 706 707 // -------------------------------------------------------------------- 708 // Check for hi bits still needing moving. Only happens for misaligned 709 // arguments to native calls. 710 if (src_second == dst_second) 711 return size; // Self copy; no move 712 assert( src_second_rc != rc_bad && dst_second_rc != rc_bad, "src_second & dst_second cannot be Bad" ); 713 714 // Check for integer reg-reg copy. Hi bits are stuck up in the top 715 // 32-bits of a 64-bit register, but are needed in low bits of another 716 // register (else it's a hi-bits-to-hi-bits copy which should have 717 // happened already as part of a 64-bit move) 718 if (src_second_rc == rc_int && dst_second_rc == rc_int) { 719 if (cbuf) { 720 __ mov(reg_to_register_object(Matcher::_regEncode[dst_second]), reg_to_register_object(Matcher::_regEncode[src_second])); 721#ifndef PRODUCT 722 } else if (!do_size) { 723 if (size != 0) st->print("\n\t"); 724 st->print("MOV R_%s, R_%s\t# spill high", 725 Matcher::regName[dst_second], 726 Matcher::regName[src_second]); 727#endif 728 } 729 return size+4; 730 } 731 732 // Check for high word integer store 733 if (src_second_rc == rc_int && dst_second_rc == rc_stack) { 734 int offset = ra_->reg2offset(dst_second); 735 736 if (cbuf && !is_memoryP(offset)) { 737 ra_->C->record_method_not_compilable("unable to handle large constant offsets"); 738 return 0; 739 } else { 740 if (cbuf) { 741 __ str(reg_to_register_object(Matcher::_regEncode[src_second]), Address(SP, offset)); 742#ifndef PRODUCT 743 } else if (!do_size) { 744 if (size != 0) st->print("\n\t"); 745 st->print("STR R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_second), offset); 746#endif 747 } 748 } 749 return size + 4; 750 } 751 752 // Check for high word integer load 753 if (dst_second_rc == rc_int && src_second_rc == rc_stack) { 754 int offset = ra_->reg2offset(src_second); 755 if (cbuf && !is_memoryP(offset)) { 756 ra_->C->record_method_not_compilable("unable to handle large constant offsets"); 757 return 0; 758 } else { 759 if (cbuf) { 760 __ ldr(reg_to_register_object(Matcher::_regEncode[dst_second]), Address(SP, offset)); 761#ifndef PRODUCT 762 } else if (!do_size) { 763 if (size != 0) st->print("\n\t"); 764 st->print("LDR R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_second), offset); 765#endif 766 } 767 } 768 return size + 4; 769 } 770 771 Unimplemented(); 772 return 0; // Mute compiler 773} 774 775#ifndef PRODUCT 776void MachSpillCopyNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { 777 implementation( NULL, ra_, false, st ); 778} 779#endif 780 781void MachSpillCopyNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { 782 implementation( &cbuf, ra_, false, NULL ); 783} 784 785uint MachSpillCopyNode::size(PhaseRegAlloc *ra_) const { 786 return implementation( NULL, ra_, true, NULL ); 787} 788 789//============================================================================= 790#ifndef PRODUCT 791void MachNopNode::format( PhaseRegAlloc *, outputStream *st ) const { 792 st->print("NOP \t# %d bytes pad for loops and calls", 4 * _count); 793} 794#endif 795 796void MachNopNode::emit(CodeBuffer &cbuf, PhaseRegAlloc * ) const { 797 C2_MacroAssembler _masm(&cbuf); 798 for(int i = 0; i < _count; i += 1) { 799 __ nop(); 800 } 801} 802 803uint MachNopNode::size(PhaseRegAlloc *ra_) const { 804 return 4 * _count; 805} 806 807 808//============================================================================= 809#ifndef PRODUCT 810void BoxLockNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { 811 int offset = ra_->reg2offset(in_RegMask(0).find_first_elem()); 812 int reg = ra_->get_reg_first(this); 813 st->print("ADD %s,R_SP+#%d",Matcher::regName[reg], offset); 814} 815#endif 816 817void BoxLockNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { 818 C2_MacroAssembler _masm(&cbuf); 819 int offset = ra_->reg2offset(in_RegMask(0).find_first_elem()); 820 int reg = ra_->get_encode(this); 821 Register dst = reg_to_register_object(reg); 822 823 if (is_aimm(offset)) { 824 __ add(dst, SP, offset); 825 } else { 826 __ mov_slow(dst, offset); 827 __ add(dst, SP, dst); 828 } 829} 830 831uint BoxLockNode::size(PhaseRegAlloc *ra_) const { 832 // BoxLockNode is not a MachNode, so we can't just call MachNode::size(ra_) 833 assert(ra_ == ra_->C->regalloc(), "sanity"); 834 return ra_->C->output()->scratch_emit_size(this); 835} 836 837//============================================================================= 838#ifndef PRODUCT 839#define R_RTEMP "R_R12" 840void MachUEPNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { 841 st->print_cr("\nUEP:"); 842 if (UseCompressedClassPointers) { 843 st->print_cr("\tLDR_w " R_RTEMP ",[R_R0 + oopDesc::klass_offset_in_bytes]\t! Inline cache check"); 844 st->print_cr("\tdecode_klass " R_RTEMP); 845 } else { 846 st->print_cr("\tLDR " R_RTEMP ",[R_R0 + oopDesc::klass_offset_in_bytes]\t! Inline cache check"); 847 } 848 st->print_cr("\tCMP " R_RTEMP ",R_R8" ); 849 st->print ("\tB.NE SharedRuntime::handle_ic_miss_stub"); 850} 851#endif 852 853void MachUEPNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { 854 C2_MacroAssembler _masm(&cbuf); 855 Register iCache = reg_to_register_object(Matcher::inline_cache_reg_encode()); 856 assert(iCache == Ricklass, "should be"); 857 Register receiver = R0; 858 859 __ load_klass(Rtemp, receiver); 860 __ cmp(Rtemp, iCache); 861 __ jump(SharedRuntime::get_ic_miss_stub(), relocInfo::runtime_call_type, noreg, ne); 862} 863 864uint MachUEPNode::size(PhaseRegAlloc *ra_) const { 865 return MachNode::size(ra_); 866} 867 868 869//============================================================================= 870 871// Emit exception handler code. 872int HandlerImpl::emit_exception_handler(CodeBuffer& cbuf) { 873 C2_MacroAssembler _masm(&cbuf); 874 875 address base = __ start_a_stub(size_exception_handler()); 876 if (base == NULL) { 877 ciEnv::current()->record_failure("CodeCache is full"); 878 return 0; // CodeBuffer::expand failed 879 } 880 881 int offset = __ offset(); 882 883 // OK to trash LR, because exception blob will kill it 884 __ jump(OptoRuntime::exception_blob()->entry_point(), relocInfo::runtime_call_type, LR_tmp); 885 886 assert(__ offset() - offset <= (int) size_exception_handler(), "overflow"); 887 888 __ end_a_stub(); 889 890 return offset; 891} 892 893int HandlerImpl::emit_deopt_handler(CodeBuffer& cbuf) { 894 // Can't use any of the current frame's registers as we may have deopted 895 // at a poll and everything can be live. 896 C2_MacroAssembler _masm(&cbuf); 897 898 address base = __ start_a_stub(size_deopt_handler()); 899 if (base == NULL) { 900 ciEnv::current()->record_failure("CodeCache is full"); 901 return 0; // CodeBuffer::expand failed 902 } 903 904 int offset = __ offset(); 905 address deopt_pc = __ pc(); 906 907 __ sub(SP, SP, wordSize); // make room for saved PC 908 __ push(LR); // save LR that may be live when we get here 909 __ mov_relative_address(LR, deopt_pc); 910 __ str(LR, Address(SP, wordSize)); // save deopt PC 911 __ pop(LR); // restore LR 912 __ jump(SharedRuntime::deopt_blob()->unpack(), relocInfo::runtime_call_type, noreg); 913 914 assert(__ offset() - offset <= (int) size_deopt_handler(), "overflow"); 915 916 __ end_a_stub(); 917 return offset; 918} 919 920const bool Matcher::match_rule_supported(int opcode) { 921 if (!has_match_rule(opcode)) 922 return false; 923 924 switch (opcode) { 925 case Op_PopCountI: 926 case Op_PopCountL: 927 if (!UsePopCountInstruction) 928 return false; 929 break; 930 case Op_LShiftCntV: 931 case Op_RShiftCntV: 932 case Op_AddVB: 933 case Op_AddVS: 934 case Op_AddVI: 935 case Op_AddVL: 936 case Op_SubVB: 937 case Op_SubVS: 938 case Op_SubVI: 939 case Op_SubVL: 940 case Op_MulVS: 941 case Op_MulVI: 942 case Op_LShiftVB: 943 case Op_LShiftVS: 944 case Op_LShiftVI: 945 case Op_LShiftVL: 946 case Op_RShiftVB: 947 case Op_RShiftVS: 948 case Op_RShiftVI: 949 case Op_RShiftVL: 950 case Op_URShiftVB: 951 case Op_URShiftVS: 952 case Op_URShiftVI: 953 case Op_URShiftVL: 954 case Op_AndV: 955 case Op_OrV: 956 case Op_XorV: 957 return VM_Version::has_simd(); 958 case Op_LoadVector: 959 case Op_StoreVector: 960 case Op_AddVF: 961 case Op_SubVF: 962 case Op_MulVF: 963 return VM_Version::has_vfp() || VM_Version::has_simd(); 964 case Op_AddVD: 965 case Op_SubVD: 966 case Op_MulVD: 967 case Op_DivVF: 968 case Op_DivVD: 969 return VM_Version::has_vfp(); 970 } 971 972 return true; // Per default match rules are supported. 973} 974 975const bool Matcher::match_rule_supported_vector(int opcode, int vlen, BasicType bt) { 976 977 // TODO 978 // identify extra cases that we might want to provide match rules for 979 // e.g. Op_ vector nodes and other intrinsics while guarding with vlen 980 bool ret_value = match_rule_supported(opcode) && vector_size_supported(bt, vlen); 981 // Add rules here. 982 983 return ret_value; // Per default match rules are supported. 984} 985 986const RegMask* Matcher::predicate_reg_mask(void) { 987 return NULL; 988} 989 990const TypeVect* Matcher::predicate_reg_type(const Type* elemTy, int length) { 991 return NULL; 992} 993 994// Vector calling convention not yet implemented. 995const bool Matcher::supports_vector_calling_convention(void) { 996 return false; 997} 998 999OptoRegPair Matcher::vector_return_value(uint ideal_reg) { 1000 Unimplemented(); 1001 return OptoRegPair(0, 0); 1002} 1003 1004const int Matcher::float_pressure(int default_pressure_threshold) { 1005 return default_pressure_threshold; 1006} 1007 1008// Vector width in bytes 1009const int Matcher::vector_width_in_bytes(BasicType bt) { 1010 return MaxVectorSize; 1011} 1012 1013const int Matcher::scalable_vector_reg_size(const BasicType bt) { 1014 return -1; 1015} 1016 1017// Vector ideal reg corresponding to specified size in bytes 1018const uint Matcher::vector_ideal_reg(int size) { 1019 assert(MaxVectorSize >= size, ""); 1020 switch(size) { 1021 case 8: return Op_VecD; 1022 case 16: return Op_VecX; 1023 } 1024 ShouldNotReachHere(); 1025 return 0; 1026} 1027 1028// Limits on vector size (number of elements) loaded into vector. 1029const int Matcher::max_vector_size(const BasicType bt) { 1030 assert(is_java_primitive(bt), "only primitive type vectors"); 1031 return vector_width_in_bytes(bt)/type2aelembytes(bt); 1032} 1033 1034const int Matcher::min_vector_size(const BasicType bt) { 1035 assert(is_java_primitive(bt), "only primitive type vectors"); 1036 return 8/type2aelembytes(bt); 1037} 1038 1039// Is this branch offset short enough that a short branch can be used? 1040// 1041// NOTE: If the platform does not provide any short branch variants, then 1042// this method should return false for offset 0. 1043bool Matcher::is_short_branch_offset(int rule, int br_size, int offset) { 1044 // The passed offset is relative to address of the branch. 1045 // On ARM a branch displacement is calculated relative to address 1046 // of the branch + 8. 1047 // 1048 // offset -= 8; 1049 // return (Assembler::is_simm24(offset)); 1050 return false; 1051} 1052 1053MachOper* Matcher::pd_specialize_generic_vector_operand(MachOper* original_opnd, uint ideal_reg, bool is_temp) { 1054 ShouldNotReachHere(); // generic vector operands not supported 1055 return NULL; 1056} 1057 1058bool Matcher::is_generic_reg2reg_move(MachNode* m) { 1059 ShouldNotReachHere(); // generic vector operands not supported 1060 return false; 1061} 1062 1063bool Matcher::is_generic_vector(MachOper* opnd) { 1064 ShouldNotReachHere(); // generic vector operands not supported 1065 return false; 1066} 1067 1068// Should the matcher clone input 'm' of node 'n'? 1069bool Matcher::pd_clone_node(Node* n, Node* m, Matcher::MStack& mstack) { 1070 if (is_vshift_con_pattern(n, m)) { // ShiftV src (ShiftCntV con) 1071 mstack.push(m, Visit); // m = ShiftCntV 1072 return true; 1073 } 1074 return false; 1075} 1076 1077// Should the Matcher clone shifts on addressing modes, expecting them 1078// to be subsumed into complex addressing expressions or compute them 1079// into registers? 1080bool Matcher::pd_clone_address_expressions(AddPNode* m, Matcher::MStack& mstack, VectorSet& address_visited) { 1081 return clone_base_plus_offset_address(m, mstack, address_visited); 1082} 1083 1084// Return whether or not this register is ever used as an argument. This 1085// function is used on startup to build the trampoline stubs in generateOptoStub. 1086// Registers not mentioned will be killed by the VM call in the trampoline, and 1087// arguments in those registers not be available to the callee. 1088bool Matcher::can_be_java_arg( int reg ) { 1089 if (reg == R_R0_num || 1090 reg == R_R1_num || 1091 reg == R_R2_num || 1092 reg == R_R3_num) return true; 1093 1094 if (reg >= R_S0_num && 1095 reg <= R_S13_num) return true; 1096 return false; 1097} 1098 1099bool Matcher::is_spillable_arg( int reg ) { 1100 return can_be_java_arg(reg); 1101} 1102 1103bool Matcher::use_asm_for_ldiv_by_con( jlong divisor ) { 1104 return false; 1105} 1106 1107// Register for DIVI projection of divmodI 1108RegMask Matcher::divI_proj_mask() { 1109 ShouldNotReachHere(); 1110 return RegMask(); 1111} 1112 1113// Register for MODI projection of divmodI 1114RegMask Matcher::modI_proj_mask() { 1115 ShouldNotReachHere(); 1116 return RegMask(); 1117} 1118 1119// Register for DIVL projection of divmodL 1120RegMask Matcher::divL_proj_mask() { 1121 ShouldNotReachHere(); 1122 return RegMask(); 1123} 1124 1125// Register for MODL projection of divmodL 1126RegMask Matcher::modL_proj_mask() { 1127 ShouldNotReachHere(); 1128 return RegMask(); 1129} 1130 1131const RegMask Matcher::method_handle_invoke_SP_save_mask() { 1132 return FP_REGP_mask(); 1133} 1134 1135bool maybe_far_call(const CallNode *n) { 1136 return !MacroAssembler::_reachable_from_cache(n->as_Call()->entry_point()); 1137} 1138 1139bool maybe_far_call(const MachCallNode *n) { 1140 return !MacroAssembler::_reachable_from_cache(n->as_MachCall()->entry_point()); 1141} 1142 1143%} 1144 1145//----------ENCODING BLOCK----------------------------------------------------- 1146// This block specifies the encoding classes used by the compiler to output 1147// byte streams. Encoding classes are parameterized macros used by 1148// Machine Instruction Nodes in order to generate the bit encoding of the 1149// instruction. Operands specify their base encoding interface with the 1150// interface keyword. There are currently supported four interfaces, 1151// REG_INTER, CONST_INTER, MEMORY_INTER, & COND_INTER. REG_INTER causes an 1152// operand to generate a function which returns its register number when 1153// queried. CONST_INTER causes an operand to generate a function which 1154// returns the value of the constant when queried. MEMORY_INTER causes an 1155// operand to generate four functions which return the Base Register, the 1156// Index Register, the Scale Value, and the Offset Value of the operand when 1157// queried. COND_INTER causes an operand to generate six functions which 1158// return the encoding code (ie - encoding bits for the instruction) 1159// associated with each basic boolean condition for a conditional instruction. 1160// 1161// Instructions specify two basic values for encoding. Again, a function 1162// is available to check if the constant displacement is an oop. They use the 1163// ins_encode keyword to specify their encoding classes (which must be 1164// a sequence of enc_class names, and their parameters, specified in 1165// the encoding block), and they use the 1166// opcode keyword to specify, in order, their primary, secondary, and 1167// tertiary opcode. Only the opcode sections which a particular instruction 1168// needs for encoding need to be specified. 1169encode %{ 1170 enc_class call_epilog %{ 1171 // nothing 1172 %} 1173 1174 enc_class Java_To_Runtime (method meth) %{ 1175 // CALL directly to the runtime 1176 emit_call_reloc(cbuf, as_MachCall(), $meth, runtime_call_Relocation::spec()); 1177 %} 1178 1179 enc_class Java_Static_Call (method meth) %{ 1180 // CALL to fixup routine. Fixup routine uses ScopeDesc info to determine 1181 // who we intended to call. 1182 1183 if ( !_method) { 1184 emit_call_reloc(cbuf, as_MachCall(), $meth, runtime_call_Relocation::spec()); 1185 } else { 1186 int method_index = resolved_method_index(cbuf); 1187 RelocationHolder rspec = _optimized_virtual ? opt_virtual_call_Relocation::spec(method_index) 1188 : static_call_Relocation::spec(method_index); 1189 emit_call_reloc(cbuf, as_MachCall(), $meth, rspec); 1190 1191 // Emit stubs for static call. 1192 address stub = CompiledStaticCall::emit_to_interp_stub(cbuf); 1193 if (stub == NULL) { 1194 ciEnv::current()->record_failure("CodeCache is full"); 1195 return; 1196 } 1197 } 1198 %} 1199 1200 enc_class save_last_PC %{ 1201 // preserve mark 1202 address mark = cbuf.insts()->mark(); 1203 debug_only(int off0 = cbuf.insts_size()); 1204 C2_MacroAssembler _masm(&cbuf); 1205 int ret_addr_offset = as_MachCall()->ret_addr_offset(); 1206 __ adr(LR, mark + ret_addr_offset); 1207 __ str(LR, Address(Rthread, JavaThread::last_Java_pc_offset())); 1208 debug_only(int off1 = cbuf.insts_size()); 1209 assert(off1 - off0 == 2 * Assembler::InstructionSize, "correct size prediction"); 1210 // restore mark 1211 cbuf.insts()->set_mark(mark); 1212 %} 1213 1214 enc_class preserve_SP %{ 1215 // preserve mark 1216 address mark = cbuf.insts()->mark(); 1217 debug_only(int off0 = cbuf.insts_size()); 1218 C2_MacroAssembler _masm(&cbuf); 1219 // FP is preserved across all calls, even compiled calls. 1220 // Use it to preserve SP in places where the callee might change the SP. 1221 __ mov(Rmh_SP_save, SP); 1222 debug_only(int off1 = cbuf.insts_size()); 1223 assert(off1 - off0 == 4, "correct size prediction"); 1224 // restore mark 1225 cbuf.insts()->set_mark(mark); 1226 %} 1227 1228 enc_class restore_SP %{ 1229 C2_MacroAssembler _masm(&cbuf); 1230 __ mov(SP, Rmh_SP_save); 1231 %} 1232 1233 enc_class Java_Dynamic_Call (method meth) %{ 1234 C2_MacroAssembler _masm(&cbuf); 1235 Register R8_ic_reg = reg_to_register_object(Matcher::inline_cache_reg_encode()); 1236 assert(R8_ic_reg == Ricklass, "should be"); 1237 __ set_inst_mark(); 1238 __ movw(R8_ic_reg, ((unsigned int)Universe::non_oop_word()) & 0xffff); 1239 __ movt(R8_ic_reg, ((unsigned int)Universe::non_oop_word()) >> 16); 1240 address virtual_call_oop_addr = __ inst_mark(); 1241 // CALL to fixup routine. Fixup routine uses ScopeDesc info to determine 1242 // who we intended to call. 1243 int method_index = resolved_method_index(cbuf); 1244 __ relocate(virtual_call_Relocation::spec(virtual_call_oop_addr, method_index)); 1245 emit_call_reloc(cbuf, as_MachCall(), $meth, RelocationHolder::none); 1246 %} 1247 1248 enc_class LdReplImmI(immI src, regD dst, iRegI tmp, int cnt, int wth) %{ 1249 // FIXME: load from constant table? 1250 // Load a constant replicated "count" times with width "width" 1251 int count = $cnt$$constant; 1252 int width = $wth$$constant; 1253 assert(count*width == 4, "sanity"); 1254 int val = $src$$constant; 1255 if (width < 4) { 1256 int bit_width = width * 8; 1257 val &= (((int)1) << bit_width) - 1; // mask off sign bits 1258 for (int i = 0; i < count - 1; i++) { 1259 val |= (val << bit_width); 1260 } 1261 } 1262 C2_MacroAssembler _masm(&cbuf); 1263 1264 if (val == -1) { 1265 __ mvn($tmp$$Register, 0); 1266 } else if (val == 0) { 1267 __ mov($tmp$$Register, 0); 1268 } else { 1269 __ movw($tmp$$Register, val & 0xffff); 1270 __ movt($tmp$$Register, (unsigned int)val >> 16); 1271 } 1272 __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register); 1273 %} 1274 1275 enc_class LdReplImmF(immF src, regD dst, iRegI tmp) %{ 1276 // Replicate float con 2 times and pack into vector (8 bytes) in regD. 1277 float fval = $src$$constant; 1278 int val = *((int*)&fval); 1279 C2_MacroAssembler _masm(&cbuf); 1280 1281 if (val == -1) { 1282 __ mvn($tmp$$Register, 0); 1283 } else if (val == 0) { 1284 __ mov($tmp$$Register, 0); 1285 } else { 1286 __ movw($tmp$$Register, val & 0xffff); 1287 __ movt($tmp$$Register, (unsigned int)val >> 16); 1288 } 1289 __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register); 1290 %} 1291 1292 enc_class enc_String_Compare(R0RegP str1, R1RegP str2, R2RegI cnt1, R3RegI cnt2, iRegI result, iRegI tmp1, iRegI tmp2) %{ 1293 Label Ldone, Lloop; 1294 C2_MacroAssembler _masm(&cbuf); 1295 1296 Register str1_reg = $str1$$Register; 1297 Register str2_reg = $str2$$Register; 1298 Register cnt1_reg = $cnt1$$Register; // int 1299 Register cnt2_reg = $cnt2$$Register; // int 1300 Register tmp1_reg = $tmp1$$Register; 1301 Register tmp2_reg = $tmp2$$Register; 1302 Register result_reg = $result$$Register; 1303 1304 assert_different_registers(str1_reg, str2_reg, cnt1_reg, cnt2_reg, tmp1_reg, tmp2_reg); 1305 1306 // Compute the minimum of the string lengths(str1_reg) and the 1307 // difference of the string lengths (stack) 1308 1309 // See if the lengths are different, and calculate min in str1_reg. 1310 // Stash diff in tmp2 in case we need it for a tie-breaker. 1311 __ subs_32(tmp2_reg, cnt1_reg, cnt2_reg); 1312 __ mov(cnt1_reg, AsmOperand(cnt1_reg, lsl, exact_log2(sizeof(jchar)))); // scale the limit 1313 __ mov(cnt1_reg, AsmOperand(cnt2_reg, lsl, exact_log2(sizeof(jchar))), pl); // scale the limit 1314 1315 // reallocate cnt1_reg, cnt2_reg, result_reg 1316 // Note: limit_reg holds the string length pre-scaled by 2 1317 Register limit_reg = cnt1_reg; 1318 Register chr2_reg = cnt2_reg; 1319 Register chr1_reg = tmp1_reg; 1320 // str{12} are the base pointers 1321 1322 // Is the minimum length zero? 1323 __ cmp_32(limit_reg, 0); 1324 if (result_reg != tmp2_reg) { 1325 __ mov(result_reg, tmp2_reg, eq); 1326 } 1327 __ b(Ldone, eq); 1328 1329 // Load first characters 1330 __ ldrh(chr1_reg, Address(str1_reg, 0)); 1331 __ ldrh(chr2_reg, Address(str2_reg, 0)); 1332 1333 // Compare first characters 1334 __ subs(chr1_reg, chr1_reg, chr2_reg); 1335 if (result_reg != chr1_reg) { 1336 __ mov(result_reg, chr1_reg, ne); 1337 } 1338 __ b(Ldone, ne); 1339 1340 { 1341 // Check after comparing first character to see if strings are equivalent 1342 // Check if the strings start at same location 1343 __ cmp(str1_reg, str2_reg); 1344 // Check if the length difference is zero 1345 __ cond_cmp(tmp2_reg, 0, eq); 1346 __ mov(result_reg, 0, eq); // result is zero 1347 __ b(Ldone, eq); 1348 // Strings might not be equal 1349 } 1350 1351 __ subs(chr1_reg, limit_reg, 1 * sizeof(jchar)); 1352 if (result_reg != tmp2_reg) { 1353 __ mov(result_reg, tmp2_reg, eq); 1354 } 1355 __ b(Ldone, eq); 1356 1357 // Shift str1_reg and str2_reg to the end of the arrays, negate limit 1358 __ add(str1_reg, str1_reg, limit_reg); 1359 __ add(str2_reg, str2_reg, limit_reg); 1360 __ neg(limit_reg, chr1_reg); // limit = -(limit-2) 1361 1362 // Compare the rest of the characters 1363 __ bind(Lloop); 1364 __ ldrh(chr1_reg, Address(str1_reg, limit_reg)); 1365 __ ldrh(chr2_reg, Address(str2_reg, limit_reg)); 1366 __ subs(chr1_reg, chr1_reg, chr2_reg); 1367 if (result_reg != chr1_reg) { 1368 __ mov(result_reg, chr1_reg, ne); 1369 } 1370 __ b(Ldone, ne); 1371 1372 __ adds(limit_reg, limit_reg, sizeof(jchar)); 1373 __ b(Lloop, ne); 1374 1375 // If strings are equal up to min length, return the length difference. 1376 if (result_reg != tmp2_reg) { 1377 __ mov(result_reg, tmp2_reg); 1378 } 1379 1380 // Otherwise, return the difference between the first mismatched chars. 1381 __ bind(Ldone); 1382 %} 1383 1384 enc_class enc_String_Equals(R0RegP str1, R1RegP str2, R2RegI cnt, iRegI result, iRegI tmp1, iRegI tmp2) %{ 1385 Label Lchar, Lchar_loop, Ldone, Lequal; 1386 C2_MacroAssembler _masm(&cbuf); 1387 1388 Register str1_reg = $str1$$Register; 1389 Register str2_reg = $str2$$Register; 1390 Register cnt_reg = $cnt$$Register; // int 1391 Register tmp1_reg = $tmp1$$Register; 1392 Register tmp2_reg = $tmp2$$Register; 1393 Register result_reg = $result$$Register; 1394 1395 assert_different_registers(str1_reg, str2_reg, cnt_reg, tmp1_reg, tmp2_reg, result_reg); 1396 1397 __ cmp(str1_reg, str2_reg); //same char[] ? 1398 __ b(Lequal, eq); 1399 1400 __ cbz_32(cnt_reg, Lequal); // count == 0 1401 1402 //rename registers 1403 Register limit_reg = cnt_reg; 1404 Register chr1_reg = tmp1_reg; 1405 Register chr2_reg = tmp2_reg; 1406 1407 __ logical_shift_left(limit_reg, limit_reg, exact_log2(sizeof(jchar))); 1408 1409 //check for alignment and position the pointers to the ends 1410 __ orr(chr1_reg, str1_reg, str2_reg); 1411 __ tst(chr1_reg, 0x3); 1412 1413 // notZero means at least one not 4-byte aligned. 1414 // We could optimize the case when both arrays are not aligned 1415 // but it is not frequent case and it requires additional checks. 1416 __ b(Lchar, ne); 1417 1418 // Compare char[] arrays aligned to 4 bytes. 1419 __ char_arrays_equals(str1_reg, str2_reg, limit_reg, result_reg, 1420 chr1_reg, chr2_reg, Ldone); 1421 1422 __ b(Lequal); // equal 1423 1424 // char by char compare 1425 __ bind(Lchar); 1426 __ mov(result_reg, 0); 1427 __ add(str1_reg, limit_reg, str1_reg); 1428 __ add(str2_reg, limit_reg, str2_reg); 1429 __ neg(limit_reg, limit_reg); //negate count 1430 1431 // Lchar_loop 1432 __ bind(Lchar_loop); 1433 __ ldrh(chr1_reg, Address(str1_reg, limit_reg)); 1434 __ ldrh(chr2_reg, Address(str2_reg, limit_reg)); 1435 __ cmp(chr1_reg, chr2_reg); 1436 __ b(Ldone, ne); 1437 __ adds(limit_reg, limit_reg, sizeof(jchar)); 1438 __ b(Lchar_loop, ne); 1439 1440 __ bind(Lequal); 1441 __ mov(result_reg, 1); //equal 1442 1443 __ bind(Ldone); 1444 %} 1445 1446 enc_class enc_Array_Equals(R0RegP ary1, R1RegP ary2, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI result) %{ 1447 Label Ldone, Lloop, Lequal; 1448 C2_MacroAssembler _masm(&cbuf); 1449 1450 Register ary1_reg = $ary1$$Register; 1451 Register ary2_reg = $ary2$$Register; 1452 Register tmp1_reg = $tmp1$$Register; 1453 Register tmp2_reg = $tmp2$$Register; 1454 Register tmp3_reg = $tmp3$$Register; 1455 Register result_reg = $result$$Register; 1456 1457 assert_different_registers(ary1_reg, ary2_reg, tmp1_reg, tmp2_reg, tmp3_reg, result_reg); 1458 1459 int length_offset = arrayOopDesc::length_offset_in_bytes(); 1460 int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); 1461 1462 // return true if the same array 1463 __ teq(ary1_reg, ary2_reg); 1464 __ mov(result_reg, 1, eq); 1465 __ b(Ldone, eq); // equal 1466 1467 __ tst(ary1_reg, ary1_reg); 1468 __ mov(result_reg, 0, eq); 1469 __ b(Ldone, eq); // not equal 1470 1471 __ tst(ary2_reg, ary2_reg); 1472 __ mov(result_reg, 0, eq); 1473 __ b(Ldone, eq); // not equal 1474 1475 //load the lengths of arrays 1476 __ ldr_s32(tmp1_reg, Address(ary1_reg, length_offset)); // int 1477 __ ldr_s32(tmp2_reg, Address(ary2_reg, length_offset)); // int 1478 1479 // return false if the two arrays are not equal length 1480 __ teq_32(tmp1_reg, tmp2_reg); 1481 __ mov(result_reg, 0, ne); 1482 __ b(Ldone, ne); // not equal 1483 1484 __ tst(tmp1_reg, tmp1_reg); 1485 __ mov(result_reg, 1, eq); 1486 __ b(Ldone, eq); // zero-length arrays are equal 1487 1488 // load array addresses 1489 __ add(ary1_reg, ary1_reg, base_offset); 1490 __ add(ary2_reg, ary2_reg, base_offset); 1491 1492 // renaming registers 1493 Register chr1_reg = tmp3_reg; // for characters in ary1 1494 Register chr2_reg = tmp2_reg; // for characters in ary2 1495 Register limit_reg = tmp1_reg; // length 1496 1497 // set byte count 1498 __ logical_shift_left_32(limit_reg, limit_reg, exact_log2(sizeof(jchar))); 1499 1500 // Compare char[] arrays aligned to 4 bytes. 1501 __ char_arrays_equals(ary1_reg, ary2_reg, limit_reg, result_reg, 1502 chr1_reg, chr2_reg, Ldone); 1503 __ bind(Lequal); 1504 __ mov(result_reg, 1); //equal 1505 1506 __ bind(Ldone); 1507 %} 1508%} 1509 1510//----------FRAME-------------------------------------------------------------- 1511// Definition of frame structure and management information. 1512// 1513// S T A C K L A Y O U T Allocators stack-slot number 1514// | (to get allocators register number 1515// G Owned by | | v add VMRegImpl::stack0) 1516// r CALLER | | 1517// o | +--------+ pad to even-align allocators stack-slot 1518// w V | pad0 | numbers; owned by CALLER 1519// t -----------+--------+----> Matcher::_in_arg_limit, unaligned 1520// h ^ | in | 5 1521// | | args | 4 Holes in incoming args owned by SELF 1522// | | | | 3 1523// | | +--------+ 1524// V | | old out| Empty on Intel, window on Sparc 1525// | old |preserve| Must be even aligned. 1526// | SP-+--------+----> Matcher::_old_SP, 8 (or 16 in LP64)-byte aligned 1527// | | in | 3 area for Intel ret address 1528// Owned by |preserve| Empty on Sparc. 1529// SELF +--------+ 1530// | | pad2 | 2 pad to align old SP 1531// | +--------+ 1 1532// | | locks | 0 1533// | +--------+----> VMRegImpl::stack0, 8 (or 16 in LP64)-byte aligned 1534// | | pad1 | 11 pad to align new SP 1535// | +--------+ 1536// | | | 10 1537// | | spills | 9 spills 1538// V | | 8 (pad0 slot for callee) 1539// -----------+--------+----> Matcher::_out_arg_limit, unaligned 1540// ^ | out | 7 1541// | | args | 6 Holes in outgoing args owned by CALLEE 1542// Owned by +--------+ 1543// CALLEE | new out| 6 Empty on Intel, window on Sparc 1544// | new |preserve| Must be even-aligned. 1545// | SP-+--------+----> Matcher::_new_SP, even aligned 1546// | | | 1547// 1548// Note 1: Only region 8-11 is determined by the allocator. Region 0-5 is 1549// known from SELF's arguments and the Java calling convention. 1550// Region 6-7 is determined per call site. 1551// Note 2: If the calling convention leaves holes in the incoming argument 1552// area, those holes are owned by SELF. Holes in the outgoing area 1553// are owned by the CALLEE. Holes should not be nessecary in the 1554// incoming area, as the Java calling convention is completely under 1555// the control of the AD file. Doubles can be sorted and packed to 1556// avoid holes. Holes in the outgoing arguments may be nessecary for 1557// varargs C calling conventions. 1558// Note 3: Region 0-3 is even aligned, with pad2 as needed. Region 3-5 is 1559// even aligned with pad0 as needed. 1560// Region 6 is even aligned. Region 6-7 is NOT even aligned; 1561// region 6-11 is even aligned; it may be padded out more so that 1562// the region from SP to FP meets the minimum stack alignment. 1563 1564frame %{ 1565 // These two registers define part of the calling convention 1566 // between compiled code and the interpreter. 1567 inline_cache_reg(R_Ricklass); // Inline Cache Register or Method* for I2C 1568 1569 // Optional: name the operand used by cisc-spilling to access [stack_pointer + offset] 1570 cisc_spilling_operand_name(indOffset); 1571 1572 // Number of stack slots consumed by a Monitor enter 1573 sync_stack_slots(1 * VMRegImpl::slots_per_word); 1574 1575 // Compiled code's Frame Pointer 1576 frame_pointer(R_R13); 1577 1578 // Stack alignment requirement 1579 stack_alignment(StackAlignmentInBytes); 1580 // LP64: Alignment size in bytes (128-bit -> 16 bytes) 1581 // !LP64: Alignment size in bytes (64-bit -> 8 bytes) 1582 1583 // Number of outgoing stack slots killed above the out_preserve_stack_slots 1584 // for calls to C. Supports the var-args backing area for register parms. 1585 // ADLC doesn't support parsing expressions, so I folded the math by hand. 1586 varargs_C_out_slots_killed( 0); 1587 1588 // The after-PROLOG location of the return address. Location of 1589 // return address specifies a type (REG or STACK) and a number 1590 // representing the register number (i.e. - use a register name) or 1591 // stack slot. 1592 // Ret Addr is on stack in slot 0 if no locks or verification or alignment. 1593 // Otherwise, it is above the locks and verification slot and alignment word 1594 return_addr(STACK - 1*VMRegImpl::slots_per_word + 1595 align_up((Compile::current()->in_preserve_stack_slots() + 1596 Compile::current()->fixed_slots()), 1597 stack_alignment_in_slots())); 1598 1599 // Location of compiled Java return values. Same as C 1600 return_value %{ 1601 return c2::return_value(ideal_reg); 1602 %} 1603 1604%} 1605 1606//----------ATTRIBUTES--------------------------------------------------------- 1607//----------Instruction Attributes--------------------------------------------- 1608ins_attrib ins_cost(DEFAULT_COST); // Required cost attribute 1609ins_attrib ins_size(32); // Required size attribute (in bits) 1610ins_attrib ins_short_branch(0); // Required flag: is this instruction a 1611 // non-matching short branch variant of some 1612 // long branch? 1613 1614//----------OPERANDS----------------------------------------------------------- 1615// Operand definitions must precede instruction definitions for correct parsing 1616// in the ADLC because operands constitute user defined types which are used in 1617// instruction definitions. 1618 1619//----------Simple Operands---------------------------------------------------- 1620// Immediate Operands 1621// Integer Immediate: 32-bit 1622operand immI() %{ 1623 match(ConI); 1624 1625 op_cost(0); 1626 // formats are generated automatically for constants and base registers 1627 format %{ %} 1628 interface(CONST_INTER); 1629%} 1630 1631// Integer Immediate: 8-bit unsigned - for VMOV 1632operand immU8() %{ 1633 predicate(0 <= n->get_int() && (n->get_int() <= 255)); 1634 match(ConI); 1635 op_cost(0); 1636 1637 format %{ %} 1638 interface(CONST_INTER); 1639%} 1640 1641// Integer Immediate: 16-bit 1642operand immI16() %{ 1643 predicate((n->get_int() >> 16) == 0 && VM_Version::supports_movw()); 1644 match(ConI); 1645 op_cost(0); 1646 1647 format %{ %} 1648 interface(CONST_INTER); 1649%} 1650 1651// Integer Immediate: offset for half and double word loads and stores 1652operand immIHD() %{ 1653 predicate(is_memoryHD(n->get_int())); 1654 match(ConI); 1655 op_cost(0); 1656 format %{ %} 1657 interface(CONST_INTER); 1658%} 1659 1660// Integer Immediate: offset for fp loads and stores 1661operand immIFP() %{ 1662 predicate(is_memoryfp(n->get_int()) && ((n->get_int() & 3) == 0)); 1663 match(ConI); 1664 op_cost(0); 1665 1666 format %{ %} 1667 interface(CONST_INTER); 1668%} 1669 1670// Valid scale values for addressing modes and shifts 1671operand immU5() %{ 1672 predicate(0 <= n->get_int() && (n->get_int() <= 31)); 1673 match(ConI); 1674 op_cost(0); 1675 1676 format %{ %} 1677 interface(CONST_INTER); 1678%} 1679 1680// Integer Immediate: 6-bit 1681operand immU6Big() %{ 1682 predicate(n->get_int() >= 32 && n->get_int() <= 63); 1683 match(ConI); 1684 op_cost(0); 1685 format %{ %} 1686 interface(CONST_INTER); 1687%} 1688 1689// Integer Immediate: 0-bit 1690operand immI0() %{ 1691 predicate(n->get_int() == 0); 1692 match(ConI); 1693 op_cost(0); 1694 1695 format %{ %} 1696 interface(CONST_INTER); 1697%} 1698 1699// Integer Immediate: the value 1 1700operand immI_1() %{ 1701 predicate(n->get_int() == 1); 1702 match(ConI); 1703 op_cost(0); 1704 1705 format %{ %} 1706 interface(CONST_INTER); 1707%} 1708 1709// Integer Immediate: the value 2 1710operand immI_2() %{ 1711 predicate(n->get_int() == 2); 1712 match(ConI); 1713 op_cost(0); 1714 1715 format %{ %} 1716 interface(CONST_INTER); 1717%} 1718 1719// Integer Immediate: the value 3 1720operand immI_3() %{ 1721 predicate(n->get_int() == 3); 1722 match(ConI); 1723 op_cost(0); 1724 1725 format %{ %} 1726 interface(CONST_INTER); 1727%} 1728 1729// Integer Immediate: the value 4 1730operand immI_4() %{ 1731 predicate(n->get_int() == 4); 1732 match(ConI); 1733 op_cost(0); 1734 1735 format %{ %} 1736 interface(CONST_INTER); 1737%} 1738 1739// Integer Immediate: the value 8 1740operand immI_8() %{ 1741 predicate(n->get_int() == 8); 1742 match(ConI); 1743 op_cost(0); 1744 1745 format %{ %} 1746 interface(CONST_INTER); 1747%} 1748 1749// Int Immediate non-negative 1750operand immU31() 1751%{ 1752 predicate(n->get_int() >= 0); 1753 match(ConI); 1754 1755 op_cost(0); 1756 format %{ %} 1757 interface(CONST_INTER); 1758%} 1759 1760// Integer Immediate: the values 32-63 1761operand immI_32_63() %{ 1762 predicate(n->get_int() >= 32 && n->get_int() <= 63); 1763 match(ConI); 1764 op_cost(0); 1765 1766 format %{ %} 1767 interface(CONST_INTER); 1768%} 1769 1770// Immediates for special shifts (sign extend) 1771 1772// Integer Immediate: the value 16 1773operand immI_16() %{ 1774 predicate(n->get_int() == 16); 1775 match(ConI); 1776 op_cost(0); 1777 1778 format %{ %} 1779 interface(CONST_INTER); 1780%} 1781 1782// Integer Immediate: the value 24 1783operand immI_24() %{ 1784 predicate(n->get_int() == 24); 1785 match(ConI); 1786 op_cost(0); 1787 1788 format %{ %} 1789 interface(CONST_INTER); 1790%} 1791 1792// Integer Immediate: the value 255 1793operand immI_255() %{ 1794 predicate( n->get_int() == 255 ); 1795 match(ConI); 1796 op_cost(0); 1797 1798 format %{ %} 1799 interface(CONST_INTER); 1800%} 1801 1802// Integer Immediate: the value 65535 1803operand immI_65535() %{ 1804 predicate(n->get_int() == 65535); 1805 match(ConI); 1806 op_cost(0); 1807 1808 format %{ %} 1809 interface(CONST_INTER); 1810%} 1811 1812// Integer Immediates for arithmetic instructions 1813 1814operand aimmI() %{ 1815 predicate(is_aimm(n->get_int())); 1816 match(ConI); 1817 op_cost(0); 1818 1819 format %{ %} 1820 interface(CONST_INTER); 1821%} 1822 1823operand aimmIneg() %{ 1824 predicate(is_aimm(-n->get_int())); 1825 match(ConI); 1826 op_cost(0); 1827 1828 format %{ %} 1829 interface(CONST_INTER); 1830%} 1831 1832operand aimmU31() %{ 1833 predicate((0 <= n->get_int()) && is_aimm(n->get_int())); 1834 match(ConI); 1835 op_cost(0); 1836 1837 format %{ %} 1838 interface(CONST_INTER); 1839%} 1840 1841// Integer Immediates for logical instructions 1842 1843operand limmI() %{ 1844 predicate(is_limmI(n->get_int())); 1845 match(ConI); 1846 op_cost(0); 1847 1848 format %{ %} 1849 interface(CONST_INTER); 1850%} 1851 1852operand limmIlow8() %{ 1853 predicate(is_limmI_low(n->get_int(), 8)); 1854 match(ConI); 1855 op_cost(0); 1856 1857 format %{ %} 1858 interface(CONST_INTER); 1859%} 1860 1861operand limmU31() %{ 1862 predicate(0 <= n->get_int() && is_limmI(n->get_int())); 1863 match(ConI); 1864 op_cost(0); 1865 1866 format %{ %} 1867 interface(CONST_INTER); 1868%} 1869 1870operand limmIn() %{ 1871 predicate(is_limmI(~n->get_int())); 1872 match(ConI); 1873 op_cost(0); 1874 1875 format %{ %} 1876 interface(CONST_INTER); 1877%} 1878 1879 1880// Long Immediate: the value FF 1881operand immL_FF() %{ 1882 predicate( n->get_long() == 0xFFL ); 1883 match(ConL); 1884 op_cost(0); 1885 1886 format %{ %} 1887 interface(CONST_INTER); 1888%} 1889 1890// Long Immediate: the value FFFF 1891operand immL_FFFF() %{ 1892 predicate( n->get_long() == 0xFFFFL ); 1893 match(ConL); 1894 op_cost(0); 1895 1896 format %{ %} 1897 interface(CONST_INTER); 1898%} 1899 1900// Pointer Immediate: 32 or 64-bit 1901operand immP() %{ 1902 match(ConP); 1903 1904 op_cost(5); 1905 // formats are generated automatically for constants and base registers 1906 format %{ %} 1907 interface(CONST_INTER); 1908%} 1909 1910operand immP0() %{ 1911 predicate(n->get_ptr() == 0); 1912 match(ConP); 1913 op_cost(0); 1914 1915 format %{ %} 1916 interface(CONST_INTER); 1917%} 1918 1919// Pointer Immediate 1920operand immN() 1921%{ 1922 match(ConN); 1923 1924 op_cost(10); 1925 format %{ %} 1926 interface(CONST_INTER); 1927%} 1928 1929operand immNKlass() 1930%{ 1931 match(ConNKlass); 1932 1933 op_cost(10); 1934 format %{ %} 1935 interface(CONST_INTER); 1936%} 1937 1938// NULL Pointer Immediate 1939operand immN0() 1940%{ 1941 predicate(n->get_narrowcon() == 0); 1942 match(ConN); 1943 1944 op_cost(0); 1945 format %{ %} 1946 interface(CONST_INTER); 1947%} 1948 1949operand immL() %{ 1950 match(ConL); 1951 op_cost(40); 1952 // formats are generated automatically for constants and base registers 1953 format %{ %} 1954 interface(CONST_INTER); 1955%} 1956 1957operand immL0() %{ 1958 predicate(n->get_long() == 0L); 1959 match(ConL); 1960 op_cost(0); 1961 // formats are generated automatically for constants and base registers 1962 format %{ %} 1963 interface(CONST_INTER); 1964%} 1965 1966// Long Immediate: 16-bit 1967operand immL16() %{ 1968 predicate(n->get_long() >= 0 && n->get_long() < (1<<16) && VM_Version::supports_movw()); 1969 match(ConL); 1970 op_cost(0); 1971 1972 format %{ %} 1973 interface(CONST_INTER); 1974%} 1975 1976// Long Immediate: low 32-bit mask 1977operand immL_32bits() %{ 1978 predicate(n->get_long() == 0xFFFFFFFFL); 1979 match(ConL); 1980 op_cost(0); 1981 1982 format %{ %} 1983 interface(CONST_INTER); 1984%} 1985 1986// Double Immediate 1987operand immD() %{ 1988 match(ConD); 1989 1990 op_cost(40); 1991 format %{ %} 1992 interface(CONST_INTER); 1993%} 1994 1995// Double Immediate: +0.0d. 1996operand immD0() %{ 1997 predicate(jlong_cast(n->getd()) == 0); 1998 1999 match(ConD); 2000 op_cost(0); 2001 format %{ %} 2002 interface(CONST_INTER); 2003%} 2004 2005operand imm8D() %{ 2006 predicate(Assembler::double_num(n->getd()).can_be_imm8()); 2007 match(ConD); 2008 2009 op_cost(0); 2010 format %{ %} 2011 interface(CONST_INTER); 2012%} 2013 2014// Float Immediate 2015operand immF() %{ 2016 match(ConF); 2017 2018 op_cost(20); 2019 format %{ %} 2020 interface(CONST_INTER); 2021%} 2022 2023// Float Immediate: +0.0f 2024operand immF0() %{ 2025 predicate(jint_cast(n->getf()) == 0); 2026 match(ConF); 2027 2028 op_cost(0); 2029 format %{ %} 2030 interface(CONST_INTER); 2031%} 2032 2033// Float Immediate: encoded as 8 bits 2034operand imm8F() %{ 2035 predicate(Assembler::float_num(n->getf()).can_be_imm8()); 2036 match(ConF); 2037 2038 op_cost(0); 2039 format %{ %} 2040 interface(CONST_INTER); 2041%} 2042 2043// Integer Register Operands 2044// Integer Register 2045operand iRegI() %{ 2046 constraint(ALLOC_IN_RC(int_reg)); 2047 match(RegI); 2048 match(R0RegI); 2049 match(R1RegI); 2050 match(R2RegI); 2051 match(R3RegI); 2052 match(R12RegI); 2053 2054 format %{ %} 2055 interface(REG_INTER); 2056%} 2057 2058// Pointer Register 2059operand iRegP() %{ 2060 constraint(ALLOC_IN_RC(ptr_reg)); 2061 match(RegP); 2062 match(R0RegP); 2063 match(R1RegP); 2064 match(R2RegP); 2065 match(RExceptionRegP); 2066 match(R8RegP); 2067 match(R9RegP); 2068 match(RthreadRegP); // FIXME: move to sp_ptr_RegP? 2069 match(R12RegP); 2070 match(LRRegP); 2071 2072 match(sp_ptr_RegP); 2073 match(store_ptr_RegP); 2074 2075 format %{ %} 2076 interface(REG_INTER); 2077%} 2078 2079// GPRs + Rthread + SP 2080operand sp_ptr_RegP() %{ 2081 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2082 match(RegP); 2083 match(iRegP); 2084 match(SPRegP); // FIXME: check cost 2085 2086 format %{ %} 2087 interface(REG_INTER); 2088%} 2089 2090 2091operand R0RegP() %{ 2092 constraint(ALLOC_IN_RC(R0_regP)); 2093 match(iRegP); 2094 2095 format %{ %} 2096 interface(REG_INTER); 2097%} 2098 2099operand R1RegP() %{ 2100 constraint(ALLOC_IN_RC(R1_regP)); 2101 match(iRegP); 2102 2103 format %{ %} 2104 interface(REG_INTER); 2105%} 2106 2107operand R8RegP() %{ 2108 constraint(ALLOC_IN_RC(R8_regP)); 2109 match(iRegP); 2110 2111 format %{ %} 2112 interface(REG_INTER); 2113%} 2114 2115operand R9RegP() %{ 2116 constraint(ALLOC_IN_RC(R9_regP)); 2117 match(iRegP); 2118 2119 format %{ %} 2120 interface(REG_INTER); 2121%} 2122 2123operand R12RegP() %{ 2124 constraint(ALLOC_IN_RC(R12_regP)); 2125 match(iRegP); 2126 2127 format %{ %} 2128 interface(REG_INTER); 2129%} 2130 2131operand R2RegP() %{ 2132 constraint(ALLOC_IN_RC(R2_regP)); 2133 match(iRegP); 2134 2135 format %{ %} 2136 interface(REG_INTER); 2137%} 2138 2139operand RExceptionRegP() %{ 2140 constraint(ALLOC_IN_RC(Rexception_regP)); 2141 match(iRegP); 2142 2143 format %{ %} 2144 interface(REG_INTER); 2145%} 2146 2147operand RthreadRegP() %{ 2148 constraint(ALLOC_IN_RC(Rthread_regP)); 2149 match(iRegP); 2150 2151 format %{ %} 2152 interface(REG_INTER); 2153%} 2154 2155operand IPRegP() %{ 2156 constraint(ALLOC_IN_RC(IP_regP)); 2157 match(iRegP); 2158 2159 format %{ %} 2160 interface(REG_INTER); 2161%} 2162 2163operand SPRegP() %{ 2164 constraint(ALLOC_IN_RC(SP_regP)); 2165 match(iRegP); 2166 2167 format %{ %} 2168 interface(REG_INTER); 2169%} 2170 2171operand LRRegP() %{ 2172 constraint(ALLOC_IN_RC(LR_regP)); 2173 match(iRegP); 2174 2175 format %{ %} 2176 interface(REG_INTER); 2177%} 2178 2179operand R0RegI() %{ 2180 constraint(ALLOC_IN_RC(R0_regI)); 2181 match(iRegI); 2182 2183 format %{ %} 2184 interface(REG_INTER); 2185%} 2186 2187operand R1RegI() %{ 2188 constraint(ALLOC_IN_RC(R1_regI)); 2189 match(iRegI); 2190 2191 format %{ %} 2192 interface(REG_INTER); 2193%} 2194 2195operand R2RegI() %{ 2196 constraint(ALLOC_IN_RC(R2_regI)); 2197 match(iRegI); 2198 2199 format %{ %} 2200 interface(REG_INTER); 2201%} 2202 2203operand R3RegI() %{ 2204 constraint(ALLOC_IN_RC(R3_regI)); 2205 match(iRegI); 2206 2207 format %{ %} 2208 interface(REG_INTER); 2209%} 2210 2211operand R12RegI() %{ 2212 constraint(ALLOC_IN_RC(R12_regI)); 2213 match(iRegI); 2214 2215 format %{ %} 2216 interface(REG_INTER); 2217%} 2218 2219// Long Register 2220operand iRegL() %{ 2221 constraint(ALLOC_IN_RC(long_reg)); 2222 match(RegL); 2223 match(R0R1RegL); 2224 match(R2R3RegL); 2225//match(iRegLex); 2226 2227 format %{ %} 2228 interface(REG_INTER); 2229%} 2230 2231operand iRegLd() %{ 2232 constraint(ALLOC_IN_RC(long_reg_align)); 2233 match(iRegL); // FIXME: allows unaligned R11/R12? 2234 2235 format %{ %} 2236 interface(REG_INTER); 2237%} 2238 2239// first long arg, or return value 2240operand R0R1RegL() %{ 2241 constraint(ALLOC_IN_RC(R0R1_regL)); 2242 match(iRegL); 2243 2244 format %{ %} 2245 interface(REG_INTER); 2246%} 2247 2248operand R2R3RegL() %{ 2249 constraint(ALLOC_IN_RC(R2R3_regL)); 2250 match(iRegL); 2251 2252 format %{ %} 2253 interface(REG_INTER); 2254%} 2255 2256// Condition Code Flag Register 2257operand flagsReg() %{ 2258 constraint(ALLOC_IN_RC(int_flags)); 2259 match(RegFlags); 2260 2261 format %{ "apsr" %} 2262 interface(REG_INTER); 2263%} 2264 2265// Result of compare to 0 (TST) 2266operand flagsReg_EQNELTGE() %{ 2267 constraint(ALLOC_IN_RC(int_flags)); 2268 match(RegFlags); 2269 2270 format %{ "apsr_EQNELTGE" %} 2271 interface(REG_INTER); 2272%} 2273 2274// Condition Code Register, unsigned comparisons. 2275operand flagsRegU() %{ 2276 constraint(ALLOC_IN_RC(int_flags)); 2277 match(RegFlags); 2278#ifdef TODO 2279 match(RegFlagsP); 2280#endif 2281 2282 format %{ "apsr_U" %} 2283 interface(REG_INTER); 2284%} 2285 2286// Condition Code Register, pointer comparisons. 2287operand flagsRegP() %{ 2288 constraint(ALLOC_IN_RC(int_flags)); 2289 match(RegFlags); 2290 2291 format %{ "apsr_P" %} 2292 interface(REG_INTER); 2293%} 2294 2295// Condition Code Register, long comparisons. 2296operand flagsRegL_LTGE() %{ 2297 constraint(ALLOC_IN_RC(int_flags)); 2298 match(RegFlags); 2299 2300 format %{ "apsr_L_LTGE" %} 2301 interface(REG_INTER); 2302%} 2303 2304operand flagsRegL_EQNE() %{ 2305 constraint(ALLOC_IN_RC(int_flags)); 2306 match(RegFlags); 2307 2308 format %{ "apsr_L_EQNE" %} 2309 interface(REG_INTER); 2310%} 2311 2312operand flagsRegL_LEGT() %{ 2313 constraint(ALLOC_IN_RC(int_flags)); 2314 match(RegFlags); 2315 2316 format %{ "apsr_L_LEGT" %} 2317 interface(REG_INTER); 2318%} 2319 2320operand flagsRegUL_LTGE() %{ 2321 constraint(ALLOC_IN_RC(int_flags)); 2322 match(RegFlags); 2323 2324 format %{ "apsr_UL_LTGE" %} 2325 interface(REG_INTER); 2326%} 2327 2328operand flagsRegUL_EQNE() %{ 2329 constraint(ALLOC_IN_RC(int_flags)); 2330 match(RegFlags); 2331 2332 format %{ "apsr_UL_EQNE" %} 2333 interface(REG_INTER); 2334%} 2335 2336operand flagsRegUL_LEGT() %{ 2337 constraint(ALLOC_IN_RC(int_flags)); 2338 match(RegFlags); 2339 2340 format %{ "apsr_UL_LEGT" %} 2341 interface(REG_INTER); 2342%} 2343 2344// Condition Code Register, floating comparisons, unordered same as "less". 2345operand flagsRegF() %{ 2346 constraint(ALLOC_IN_RC(float_flags)); 2347 match(RegFlags); 2348 2349 format %{ "fpscr_F" %} 2350 interface(REG_INTER); 2351%} 2352 2353// Vectors 2354operand vecD() %{ 2355 constraint(ALLOC_IN_RC(actual_dflt_reg)); 2356 match(VecD); 2357 2358 format %{ %} 2359 interface(REG_INTER); 2360%} 2361 2362operand vecX() %{ 2363 constraint(ALLOC_IN_RC(vectorx_reg)); 2364 match(VecX); 2365 2366 format %{ %} 2367 interface(REG_INTER); 2368%} 2369 2370operand regD() %{ 2371 constraint(ALLOC_IN_RC(actual_dflt_reg)); 2372 match(RegD); 2373 match(regD_low); 2374 2375 format %{ %} 2376 interface(REG_INTER); 2377%} 2378 2379operand regF() %{ 2380 constraint(ALLOC_IN_RC(sflt_reg)); 2381 match(RegF); 2382 2383 format %{ %} 2384 interface(REG_INTER); 2385%} 2386 2387operand regD_low() %{ 2388 constraint(ALLOC_IN_RC(dflt_low_reg)); 2389 match(RegD); 2390 2391 format %{ %} 2392 interface(REG_INTER); 2393%} 2394 2395// Special Registers 2396 2397// Method Register 2398operand inline_cache_regP(iRegP reg) %{ 2399 constraint(ALLOC_IN_RC(Ricklass_regP)); 2400 match(reg); 2401 format %{ %} 2402 interface(REG_INTER); 2403%} 2404 2405//----------Complex Operands--------------------------------------------------- 2406// Indirect Memory Reference 2407operand indirect(sp_ptr_RegP reg) %{ 2408 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2409 match(reg); 2410 2411 op_cost(100); 2412 format %{ "[$reg]" %} 2413 interface(MEMORY_INTER) %{ 2414 base($reg); 2415 index(0xf); // PC => no index 2416 scale(0x0); 2417 disp(0x0); 2418 %} 2419%} 2420 2421 2422// Indirect with Offset in ]-4096, 4096[ 2423operand indOffset12(sp_ptr_RegP reg, immI12 offset) %{ 2424 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2425 match(AddP reg offset); 2426 2427 op_cost(100); 2428 format %{ "[$reg + $offset]" %} 2429 interface(MEMORY_INTER) %{ 2430 base($reg); 2431 index(0xf); // PC => no index 2432 scale(0x0); 2433 disp($offset); 2434 %} 2435%} 2436 2437// Indirect with offset for float load/store 2438operand indOffsetFP(sp_ptr_RegP reg, immIFP offset) %{ 2439 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2440 match(AddP reg offset); 2441 2442 op_cost(100); 2443 format %{ "[$reg + $offset]" %} 2444 interface(MEMORY_INTER) %{ 2445 base($reg); 2446 index(0xf); // PC => no index 2447 scale(0x0); 2448 disp($offset); 2449 %} 2450%} 2451 2452// Indirect with Offset for half and double words 2453operand indOffsetHD(sp_ptr_RegP reg, immIHD offset) %{ 2454 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2455 match(AddP reg offset); 2456 2457 op_cost(100); 2458 format %{ "[$reg + $offset]" %} 2459 interface(MEMORY_INTER) %{ 2460 base($reg); 2461 index(0xf); // PC => no index 2462 scale(0x0); 2463 disp($offset); 2464 %} 2465%} 2466 2467// Indirect with Offset and Offset+4 in ]-1024, 1024[ 2468operand indOffsetFPx2(sp_ptr_RegP reg, immX10x2 offset) %{ 2469 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2470 match(AddP reg offset); 2471 2472 op_cost(100); 2473 format %{ "[$reg + $offset]" %} 2474 interface(MEMORY_INTER) %{ 2475 base($reg); 2476 index(0xf); // PC => no index 2477 scale(0x0); 2478 disp($offset); 2479 %} 2480%} 2481 2482// Indirect with Offset and Offset+4 in ]-4096, 4096[ 2483operand indOffset12x2(sp_ptr_RegP reg, immI12x2 offset) %{ 2484 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2485 match(AddP reg offset); 2486 2487 op_cost(100); 2488 format %{ "[$reg + $offset]" %} 2489 interface(MEMORY_INTER) %{ 2490 base($reg); 2491 index(0xf); // PC => no index 2492 scale(0x0); 2493 disp($offset); 2494 %} 2495%} 2496 2497// Indirect with Register Index 2498operand indIndex(iRegP addr, iRegX index) %{ 2499 constraint(ALLOC_IN_RC(ptr_reg)); 2500 match(AddP addr index); 2501 2502 op_cost(100); 2503 format %{ "[$addr + $index]" %} 2504 interface(MEMORY_INTER) %{ 2505 base($addr); 2506 index($index); 2507 scale(0x0); 2508 disp(0x0); 2509 %} 2510%} 2511 2512// Indirect Memory Times Scale Plus Index Register 2513operand indIndexScale(iRegP addr, iRegX index, immU5 scale) %{ 2514 constraint(ALLOC_IN_RC(ptr_reg)); 2515 match(AddP addr (LShiftX index scale)); 2516 2517 op_cost(100); 2518 format %{"[$addr + $index << $scale]" %} 2519 interface(MEMORY_INTER) %{ 2520 base($addr); 2521 index($index); 2522 scale($scale); 2523 disp(0x0); 2524 %} 2525%} 2526 2527// Operands for expressing Control Flow 2528// NOTE: Label is a predefined operand which should not be redefined in 2529// the AD file. It is generically handled within the ADLC. 2530 2531//----------Conditional Branch Operands---------------------------------------- 2532// Comparison Op - This is the operation of the comparison, and is limited to 2533// the following set of codes: 2534// L (<), LE (<=), G (>), GE (>=), E (==), NE (!=) 2535// 2536// Other attributes of the comparison, such as unsignedness, are specified 2537// by the comparison instruction that sets a condition code flags register. 2538// That result is represented by a flags operand whose subtype is appropriate 2539// to the unsignedness (etc.) of the comparison. 2540// 2541// Later, the instruction which matches both the Comparison Op (a Bool) and 2542// the flags (produced by the Cmp) specifies the coding of the comparison op 2543// by matching a specific subtype of Bool operand below, such as cmpOpU. 2544 2545operand cmpOp() %{ 2546 match(Bool); 2547 2548 format %{ "" %} 2549 interface(COND_INTER) %{ 2550 equal(0x0); 2551 not_equal(0x1); 2552 less(0xb); 2553 greater_equal(0xa); 2554 less_equal(0xd); 2555 greater(0xc); 2556 overflow(0x0); // unsupported/unimplemented 2557 no_overflow(0x0); // unsupported/unimplemented 2558 %} 2559%} 2560 2561// integer comparison with 0, signed 2562operand cmpOp0() %{ 2563 match(Bool); 2564 2565 format %{ "" %} 2566 interface(COND_INTER) %{ 2567 equal(0x0); 2568 not_equal(0x1); 2569 less(0x4); 2570 greater_equal(0x5); 2571 less_equal(0xd); // unsupported 2572 greater(0xc); // unsupported 2573 overflow(0x0); // unsupported/unimplemented 2574 no_overflow(0x0); // unsupported/unimplemented 2575 %} 2576%} 2577 2578// Comparison Op, unsigned 2579operand cmpOpU() %{ 2580 match(Bool); 2581 2582 format %{ "u" %} 2583 interface(COND_INTER) %{ 2584 equal(0x0); 2585 not_equal(0x1); 2586 less(0x3); 2587 greater_equal(0x2); 2588 less_equal(0x9); 2589 greater(0x8); 2590 overflow(0x0); // unsupported/unimplemented 2591 no_overflow(0x0); // unsupported/unimplemented 2592 %} 2593%} 2594 2595// Comparison Op, pointer (same as unsigned) 2596operand cmpOpP() %{ 2597 match(Bool); 2598 2599 format %{ "p" %} 2600 interface(COND_INTER) %{ 2601 equal(0x0); 2602 not_equal(0x1); 2603 less(0x3); 2604 greater_equal(0x2); 2605 less_equal(0x9); 2606 greater(0x8); 2607 overflow(0x0); // unsupported/unimplemented 2608 no_overflow(0x0); // unsupported/unimplemented 2609 %} 2610%} 2611 2612operand cmpOpL() %{ 2613 match(Bool); 2614 2615 format %{ "L" %} 2616 interface(COND_INTER) %{ 2617 equal(0x0); 2618 not_equal(0x1); 2619 less(0xb); 2620 greater_equal(0xa); 2621 less_equal(0xd); 2622 greater(0xc); 2623 overflow(0x0); // unsupported/unimplemented 2624 no_overflow(0x0); // unsupported/unimplemented 2625 %} 2626%} 2627 2628operand cmpOpL_commute() %{ 2629 match(Bool); 2630 2631 format %{ "L" %} 2632 interface(COND_INTER) %{ 2633 equal(0x0); 2634 not_equal(0x1); 2635 less(0xc); 2636 greater_equal(0xd); 2637 less_equal(0xa); 2638 greater(0xb); 2639 overflow(0x0); // unsupported/unimplemented 2640 no_overflow(0x0); // unsupported/unimplemented 2641 %} 2642%} 2643 2644operand cmpOpUL() %{ 2645 match(Bool); 2646 2647 format %{ "UL" %} 2648 interface(COND_INTER) %{ 2649 equal(0x0); 2650 not_equal(0x1); 2651 less(0x3); 2652 greater_equal(0x2); 2653 less_equal(0x9); 2654 greater(0x8); 2655 overflow(0x0); // unsupported/unimplemented 2656 no_overflow(0x0); // unsupported/unimplemented 2657 %} 2658%} 2659 2660operand cmpOpUL_commute() %{ 2661 match(Bool); 2662 2663 format %{ "UL" %} 2664 interface(COND_INTER) %{ 2665 equal(0x0); 2666 not_equal(0x1); 2667 less(0x8); 2668 greater_equal(0x9); 2669 less_equal(0x2); 2670 greater(0x3); 2671 overflow(0x0); // unsupported/unimplemented 2672 no_overflow(0x0); // unsupported/unimplemented 2673 %} 2674%} 2675 2676 2677//----------OPERAND CLASSES---------------------------------------------------- 2678// Operand Classes are groups of operands that are used to simplify 2679// instruction definitions by not requiring the AD writer to specify separate 2680// instructions for every form of operand when the instruction accepts 2681// multiple operand types with the same basic encoding and format. The classic 2682// case of this is memory operands. 2683 2684opclass memoryI ( indirect, indOffset12, indIndex, indIndexScale ); 2685opclass memoryP ( indirect, indOffset12, indIndex, indIndexScale ); 2686opclass memoryF ( indirect, indOffsetFP ); 2687opclass memoryF2 ( indirect, indOffsetFPx2 ); 2688opclass memoryD ( indirect, indOffsetFP ); 2689opclass memoryfp( indirect, indOffsetFP ); 2690opclass memoryB ( indirect, indIndex, indOffsetHD ); 2691opclass memoryS ( indirect, indIndex, indOffsetHD ); 2692opclass memoryL ( indirect, indIndex, indOffsetHD ); 2693 2694opclass memoryScaledI(indIndexScale); 2695opclass memoryScaledP(indIndexScale); 2696 2697// when ldrex/strex is used: 2698opclass memoryex ( indirect ); 2699opclass indIndexMemory( indIndex ); 2700opclass memorylong ( indirect, indOffset12x2 ); 2701opclass memoryvld ( indirect /* , write back mode not implemented */ ); 2702 2703//----------PIPELINE----------------------------------------------------------- 2704pipeline %{ 2705 2706//----------ATTRIBUTES--------------------------------------------------------- 2707attributes %{ 2708 fixed_size_instructions; // Fixed size instructions 2709 max_instructions_per_bundle = 4; // Up to 4 instructions per bundle 2710 instruction_unit_size = 4; // An instruction is 4 bytes long 2711 instruction_fetch_unit_size = 16; // The processor fetches one line 2712 instruction_fetch_units = 1; // of 16 bytes 2713 2714 // List of nop instructions 2715 nops( Nop_A0, Nop_A1, Nop_MS, Nop_FA, Nop_BR ); 2716%} 2717 2718//----------RESOURCES---------------------------------------------------------- 2719// Resources are the functional units available to the machine 2720resources(A0, A1, MS, BR, FA, FM, IDIV, FDIV, IALU = A0 | A1); 2721 2722//----------PIPELINE DESCRIPTION----------------------------------------------- 2723// Pipeline Description specifies the stages in the machine's pipeline 2724 2725pipe_desc(A, P, F, B, I, J, S, R, E, C, M, W, X, T, D); 2726 2727//----------PIPELINE CLASSES--------------------------------------------------- 2728// Pipeline Classes describe the stages in which input and output are 2729// referenced by the hardware pipeline. 2730 2731// Integer ALU reg-reg operation 2732pipe_class ialu_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 2733 single_instruction; 2734 dst : E(write); 2735 src1 : R(read); 2736 src2 : R(read); 2737 IALU : R; 2738%} 2739 2740// Integer ALU reg-reg long operation 2741pipe_class ialu_reg_reg_2(iRegL dst, iRegL src1, iRegL src2) %{ 2742 instruction_count(2); 2743 dst : E(write); 2744 src1 : R(read); 2745 src2 : R(read); 2746 IALU : R; 2747 IALU : R; 2748%} 2749 2750// Integer ALU reg-reg long dependent operation 2751pipe_class ialu_reg_reg_2_dep(iRegL dst, iRegL src1, iRegL src2, flagsReg cr) %{ 2752 instruction_count(1); multiple_bundles; 2753 dst : E(write); 2754 src1 : R(read); 2755 src2 : R(read); 2756 cr : E(write); 2757 IALU : R(2); 2758%} 2759 2760// Integer ALU reg-imm operaion 2761pipe_class ialu_reg_imm(iRegI dst, iRegI src1) %{ 2762 single_instruction; 2763 dst : E(write); 2764 src1 : R(read); 2765 IALU : R; 2766%} 2767 2768// Integer ALU reg-reg operation with condition code 2769pipe_class ialu_cc_reg_reg(iRegI dst, iRegI src1, iRegI src2, flagsReg cr) %{ 2770 single_instruction; 2771 dst : E(write); 2772 cr : E(write); 2773 src1 : R(read); 2774 src2 : R(read); 2775 IALU : R; 2776%} 2777 2778// Integer ALU zero-reg operation 2779pipe_class ialu_zero_reg(iRegI dst, immI0 zero, iRegI src2) %{ 2780 single_instruction; 2781 dst : E(write); 2782 src2 : R(read); 2783 IALU : R; 2784%} 2785 2786// Integer ALU zero-reg operation with condition code only 2787pipe_class ialu_cconly_zero_reg(flagsReg cr, iRegI src) %{ 2788 single_instruction; 2789 cr : E(write); 2790 src : R(read); 2791 IALU : R; 2792%} 2793 2794// Integer ALU reg-reg operation with condition code only 2795pipe_class ialu_cconly_reg_reg(flagsReg cr, iRegI src1, iRegI src2) %{ 2796 single_instruction; 2797 cr : E(write); 2798 src1 : R(read); 2799 src2 : R(read); 2800 IALU : R; 2801%} 2802 2803// Integer ALU reg-imm operation with condition code only 2804pipe_class ialu_cconly_reg_imm(flagsReg cr, iRegI src1) %{ 2805 single_instruction; 2806 cr : E(write); 2807 src1 : R(read); 2808 IALU : R; 2809%} 2810 2811// Integer ALU reg-reg-zero operation with condition code only 2812pipe_class ialu_cconly_reg_reg_zero(flagsReg cr, iRegI src1, iRegI src2, immI0 zero) %{ 2813 single_instruction; 2814 cr : E(write); 2815 src1 : R(read); 2816 src2 : R(read); 2817 IALU : R; 2818%} 2819 2820// Integer ALU reg-imm-zero operation with condition code only 2821pipe_class ialu_cconly_reg_imm_zero(flagsReg cr, iRegI src1, immI0 zero) %{ 2822 single_instruction; 2823 cr : E(write); 2824 src1 : R(read); 2825 IALU : R; 2826%} 2827 2828// Integer ALU reg-reg operation with condition code, src1 modified 2829pipe_class ialu_cc_rwreg_reg(flagsReg cr, iRegI src1, iRegI src2) %{ 2830 single_instruction; 2831 cr : E(write); 2832 src1 : E(write); 2833 src1 : R(read); 2834 src2 : R(read); 2835 IALU : R; 2836%} 2837 2838pipe_class cmpL_reg(iRegI dst, iRegL src1, iRegL src2, flagsReg cr ) %{ 2839 multiple_bundles; 2840 dst : E(write)+4; 2841 cr : E(write); 2842 src1 : R(read); 2843 src2 : R(read); 2844 IALU : R(3); 2845 BR : R(2); 2846%} 2847 2848// Integer ALU operation 2849pipe_class ialu_none(iRegI dst) %{ 2850 single_instruction; 2851 dst : E(write); 2852 IALU : R; 2853%} 2854 2855// Integer ALU reg operation 2856pipe_class ialu_reg(iRegI dst, iRegI src) %{ 2857 single_instruction; may_have_no_code; 2858 dst : E(write); 2859 src : R(read); 2860 IALU : R; 2861%} 2862 2863// Integer ALU reg conditional operation 2864// This instruction has a 1 cycle stall, and cannot execute 2865// in the same cycle as the instruction setting the condition 2866// code. We kludge this by pretending to read the condition code 2867// 1 cycle earlier, and by marking the functional units as busy 2868// for 2 cycles with the result available 1 cycle later than 2869// is really the case. 2870pipe_class ialu_reg_flags( iRegI op2_out, iRegI op2_in, iRegI op1, flagsReg cr ) %{ 2871 single_instruction; 2872 op2_out : C(write); 2873 op1 : R(read); 2874 cr : R(read); // This is really E, with a 1 cycle stall 2875 BR : R(2); 2876 MS : R(2); 2877%} 2878 2879// Integer ALU reg operation 2880pipe_class ialu_move_reg_L_to_I(iRegI dst, iRegL src) %{ 2881 single_instruction; may_have_no_code; 2882 dst : E(write); 2883 src : R(read); 2884 IALU : R; 2885%} 2886pipe_class ialu_move_reg_I_to_L(iRegL dst, iRegI src) %{ 2887 single_instruction; may_have_no_code; 2888 dst : E(write); 2889 src : R(read); 2890 IALU : R; 2891%} 2892 2893// Two integer ALU reg operations 2894pipe_class ialu_reg_2(iRegL dst, iRegL src) %{ 2895 instruction_count(2); 2896 dst : E(write); 2897 src : R(read); 2898 A0 : R; 2899 A1 : R; 2900%} 2901 2902// Two integer ALU reg operations 2903pipe_class ialu_move_reg_L_to_L(iRegL dst, iRegL src) %{ 2904 instruction_count(2); may_have_no_code; 2905 dst : E(write); 2906 src : R(read); 2907 A0 : R; 2908 A1 : R; 2909%} 2910 2911// Integer ALU imm operation 2912pipe_class ialu_imm(iRegI dst) %{ 2913 single_instruction; 2914 dst : E(write); 2915 IALU : R; 2916%} 2917 2918pipe_class ialu_imm_n(iRegI dst) %{ 2919 single_instruction; 2920 dst : E(write); 2921 IALU : R; 2922%} 2923 2924// Integer ALU reg-reg with carry operation 2925pipe_class ialu_reg_reg_cy(iRegI dst, iRegI src1, iRegI src2, iRegI cy) %{ 2926 single_instruction; 2927 dst : E(write); 2928 src1 : R(read); 2929 src2 : R(read); 2930 IALU : R; 2931%} 2932 2933// Integer ALU cc operation 2934pipe_class ialu_cc(iRegI dst, flagsReg cc) %{ 2935 single_instruction; 2936 dst : E(write); 2937 cc : R(read); 2938 IALU : R; 2939%} 2940 2941// Integer ALU cc / second IALU operation 2942pipe_class ialu_reg_ialu( iRegI dst, iRegI src ) %{ 2943 instruction_count(1); multiple_bundles; 2944 dst : E(write)+1; 2945 src : R(read); 2946 IALU : R; 2947%} 2948 2949// Integer ALU cc / second IALU operation 2950pipe_class ialu_reg_reg_ialu( iRegI dst, iRegI p, iRegI q ) %{ 2951 instruction_count(1); multiple_bundles; 2952 dst : E(write)+1; 2953 p : R(read); 2954 q : R(read); 2955 IALU : R; 2956%} 2957 2958// Integer ALU hi-lo-reg operation 2959pipe_class ialu_hi_lo_reg(iRegI dst, immI src) %{ 2960 instruction_count(1); multiple_bundles; 2961 dst : E(write)+1; 2962 IALU : R(2); 2963%} 2964 2965// Long Constant 2966pipe_class loadConL( iRegL dst, immL src ) %{ 2967 instruction_count(2); multiple_bundles; 2968 dst : E(write)+1; 2969 IALU : R(2); 2970 IALU : R(2); 2971%} 2972 2973// Pointer Constant 2974pipe_class loadConP( iRegP dst, immP src ) %{ 2975 instruction_count(0); multiple_bundles; 2976 fixed_latency(6); 2977%} 2978 2979// Long Constant small 2980pipe_class loadConLlo( iRegL dst, immL src ) %{ 2981 instruction_count(2); 2982 dst : E(write); 2983 IALU : R; 2984 IALU : R; 2985%} 2986 2987// [PHH] This is wrong for 64-bit. See LdImmF/D. 2988pipe_class loadConFD(regF dst, immF src, iRegP tmp) %{ 2989 instruction_count(1); multiple_bundles; 2990 src : R(read); 2991 dst : M(write)+1; 2992 IALU : R; 2993 MS : E; 2994%} 2995 2996// Integer ALU nop operation 2997pipe_class ialu_nop() %{ 2998 single_instruction; 2999 IALU : R; 3000%} 3001 3002// Integer ALU nop operation 3003pipe_class ialu_nop_A0() %{ 3004 single_instruction; 3005 A0 : R; 3006%} 3007 3008// Integer ALU nop operation 3009pipe_class ialu_nop_A1() %{ 3010 single_instruction; 3011 A1 : R; 3012%} 3013 3014// Integer Multiply reg-reg operation 3015pipe_class imul_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 3016 single_instruction; 3017 dst : E(write); 3018 src1 : R(read); 3019 src2 : R(read); 3020 MS : R(5); 3021%} 3022 3023pipe_class mulL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{ 3024 single_instruction; 3025 dst : E(write)+4; 3026 src1 : R(read); 3027 src2 : R(read); 3028 MS : R(6); 3029%} 3030 3031// Integer Divide reg-reg 3032pipe_class sdiv_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI temp, flagsReg cr) %{ 3033 instruction_count(1); multiple_bundles; 3034 dst : E(write); 3035 temp : E(write); 3036 src1 : R(read); 3037 src2 : R(read); 3038 temp : R(read); 3039 MS : R(38); 3040%} 3041 3042// Long Divide 3043pipe_class divL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{ 3044 dst : E(write)+71; 3045 src1 : R(read); 3046 src2 : R(read)+1; 3047 MS : R(70); 3048%} 3049 3050// Floating Point Add Float 3051pipe_class faddF_reg_reg(regF dst, regF src1, regF src2) %{ 3052 single_instruction; 3053 dst : X(write); 3054 src1 : E(read); 3055 src2 : E(read); 3056 FA : R; 3057%} 3058 3059// Floating Point Add Double 3060pipe_class faddD_reg_reg(regD dst, regD src1, regD src2) %{ 3061 single_instruction; 3062 dst : X(write); 3063 src1 : E(read); 3064 src2 : E(read); 3065 FA : R; 3066%} 3067 3068// Floating Point Conditional Move based on integer flags 3069pipe_class int_conditional_float_move (cmpOp cmp, flagsReg cr, regF dst, regF src) %{ 3070 single_instruction; 3071 dst : X(write); 3072 src : E(read); 3073 cr : R(read); 3074 FA : R(2); 3075 BR : R(2); 3076%} 3077 3078// Floating Point Conditional Move based on integer flags 3079pipe_class int_conditional_double_move (cmpOp cmp, flagsReg cr, regD dst, regD src) %{ 3080 single_instruction; 3081 dst : X(write); 3082 src : E(read); 3083 cr : R(read); 3084 FA : R(2); 3085 BR : R(2); 3086%} 3087 3088// Floating Point Multiply Float 3089pipe_class fmulF_reg_reg(regF dst, regF src1, regF src2) %{ 3090 single_instruction; 3091 dst : X(write); 3092 src1 : E(read); 3093 src2 : E(read); 3094 FM : R; 3095%} 3096 3097// Floating Point Multiply Double 3098pipe_class fmulD_reg_reg(regD dst, regD src1, regD src2) %{ 3099 single_instruction; 3100 dst : X(write); 3101 src1 : E(read); 3102 src2 : E(read); 3103 FM : R; 3104%} 3105 3106// Floating Point Divide Float 3107pipe_class fdivF_reg_reg(regF dst, regF src1, regF src2) %{ 3108 single_instruction; 3109 dst : X(write); 3110 src1 : E(read); 3111 src2 : E(read); 3112 FM : R; 3113 FDIV : C(14); 3114%} 3115 3116// Floating Point Divide Double 3117pipe_class fdivD_reg_reg(regD dst, regD src1, regD src2) %{ 3118 single_instruction; 3119 dst : X(write); 3120 src1 : E(read); 3121 src2 : E(read); 3122 FM : R; 3123 FDIV : C(17); 3124%} 3125 3126// Floating Point Move/Negate/Abs Float 3127pipe_class faddF_reg(regF dst, regF src) %{ 3128 single_instruction; 3129 dst : W(write); 3130 src : E(read); 3131 FA : R(1); 3132%} 3133 3134// Floating Point Move/Negate/Abs Double 3135pipe_class faddD_reg(regD dst, regD src) %{ 3136 single_instruction; 3137 dst : W(write); 3138 src : E(read); 3139 FA : R; 3140%} 3141 3142// Floating Point Convert F->D 3143pipe_class fcvtF2D(regD dst, regF src) %{ 3144 single_instruction; 3145 dst : X(write); 3146 src : E(read); 3147 FA : R; 3148%} 3149 3150// Floating Point Convert I->D 3151pipe_class fcvtI2D(regD dst, regF src) %{ 3152 single_instruction; 3153 dst : X(write); 3154 src : E(read); 3155 FA : R; 3156%} 3157 3158// Floating Point Convert LHi->D 3159pipe_class fcvtLHi2D(regD dst, regD src) %{ 3160 single_instruction; 3161 dst : X(write); 3162 src : E(read); 3163 FA : R; 3164%} 3165 3166// Floating Point Convert L->D 3167pipe_class fcvtL2D(regD dst, iRegL src) %{ 3168 single_instruction; 3169 dst : X(write); 3170 src : E(read); 3171 FA : R; 3172%} 3173 3174// Floating Point Convert L->F 3175pipe_class fcvtL2F(regF dst, iRegL src) %{ 3176 single_instruction; 3177 dst : X(write); 3178 src : E(read); 3179 FA : R; 3180%} 3181 3182// Floating Point Convert D->F 3183pipe_class fcvtD2F(regD dst, regF src) %{ 3184 single_instruction; 3185 dst : X(write); 3186 src : E(read); 3187 FA : R; 3188%} 3189 3190// Floating Point Convert I->L 3191pipe_class fcvtI2L(regD dst, regF src) %{ 3192 single_instruction; 3193 dst : X(write); 3194 src : E(read); 3195 FA : R; 3196%} 3197 3198// Floating Point Convert D->F 3199pipe_class fcvtD2I(iRegI dst, regD src, flagsReg cr) %{ 3200 instruction_count(1); multiple_bundles; 3201 dst : X(write)+6; 3202 src : E(read); 3203 FA : R; 3204%} 3205 3206// Floating Point Convert D->L 3207pipe_class fcvtD2L(regD dst, regD src, flagsReg cr) %{ 3208 instruction_count(1); multiple_bundles; 3209 dst : X(write)+6; 3210 src : E(read); 3211 FA : R; 3212%} 3213 3214// Floating Point Convert F->I 3215pipe_class fcvtF2I(regF dst, regF src, flagsReg cr) %{ 3216 instruction_count(1); multiple_bundles; 3217 dst : X(write)+6; 3218 src : E(read); 3219 FA : R; 3220%} 3221 3222// Floating Point Convert F->L 3223pipe_class fcvtF2L(regD dst, regF src, flagsReg cr) %{ 3224 instruction_count(1); multiple_bundles; 3225 dst : X(write)+6; 3226 src : E(read); 3227 FA : R; 3228%} 3229 3230// Floating Point Convert I->F 3231pipe_class fcvtI2F(regF dst, regF src) %{ 3232 single_instruction; 3233 dst : X(write); 3234 src : E(read); 3235 FA : R; 3236%} 3237 3238// Floating Point Compare 3239pipe_class faddF_fcc_reg_reg_zero(flagsRegF cr, regF src1, regF src2, immI0 zero) %{ 3240 single_instruction; 3241 cr : X(write); 3242 src1 : E(read); 3243 src2 : E(read); 3244 FA : R; 3245%} 3246 3247// Floating Point Compare 3248pipe_class faddD_fcc_reg_reg_zero(flagsRegF cr, regD src1, regD src2, immI0 zero) %{ 3249 single_instruction; 3250 cr : X(write); 3251 src1 : E(read); 3252 src2 : E(read); 3253 FA : R; 3254%} 3255 3256// Floating Add Nop 3257pipe_class fadd_nop() %{ 3258 single_instruction; 3259 FA : R; 3260%} 3261 3262// Integer Store to Memory 3263pipe_class istore_mem_reg(memoryI mem, iRegI src) %{ 3264 single_instruction; 3265 mem : R(read); 3266 src : C(read); 3267 MS : R; 3268%} 3269 3270// Integer Store to Memory 3271pipe_class istore_mem_spORreg(memoryI mem, sp_ptr_RegP src) %{ 3272 single_instruction; 3273 mem : R(read); 3274 src : C(read); 3275 MS : R; 3276%} 3277 3278// Float Store 3279pipe_class fstoreF_mem_reg(memoryF mem, RegF src) %{ 3280 single_instruction; 3281 mem : R(read); 3282 src : C(read); 3283 MS : R; 3284%} 3285 3286// Float Store 3287pipe_class fstoreF_mem_zero(memoryF mem, immF0 src) %{ 3288 single_instruction; 3289 mem : R(read); 3290 MS : R; 3291%} 3292 3293// Double Store 3294pipe_class fstoreD_mem_reg(memoryD mem, RegD src) %{ 3295 instruction_count(1); 3296 mem : R(read); 3297 src : C(read); 3298 MS : R; 3299%} 3300 3301// Double Store 3302pipe_class fstoreD_mem_zero(memoryD mem, immD0 src) %{ 3303 single_instruction; 3304 mem : R(read); 3305 MS : R; 3306%} 3307 3308// Integer Load (when sign bit propagation not needed) 3309pipe_class iload_mem(iRegI dst, memoryI mem) %{ 3310 single_instruction; 3311 mem : R(read); 3312 dst : C(write); 3313 MS : R; 3314%} 3315 3316// Integer Load (when sign bit propagation or masking is needed) 3317pipe_class iload_mask_mem(iRegI dst, memoryI mem) %{ 3318 single_instruction; 3319 mem : R(read); 3320 dst : M(write); 3321 MS : R; 3322%} 3323 3324// Float Load 3325pipe_class floadF_mem(regF dst, memoryF mem) %{ 3326 single_instruction; 3327 mem : R(read); 3328 dst : M(write); 3329 MS : R; 3330%} 3331 3332// Float Load 3333pipe_class floadD_mem(regD dst, memoryD mem) %{ 3334 instruction_count(1); multiple_bundles; // Again, unaligned argument is only multiple case 3335 mem : R(read); 3336 dst : M(write); 3337 MS : R; 3338%} 3339 3340// Memory Nop 3341pipe_class mem_nop() %{ 3342 single_instruction; 3343 MS : R; 3344%} 3345 3346pipe_class sethi(iRegP dst, immI src) %{ 3347 single_instruction; 3348 dst : E(write); 3349 IALU : R; 3350%} 3351 3352pipe_class loadPollP(iRegP poll) %{ 3353 single_instruction; 3354 poll : R(read); 3355 MS : R; 3356%} 3357 3358pipe_class br(Universe br, label labl) %{ 3359 single_instruction_with_delay_slot; 3360 BR : R; 3361%} 3362 3363pipe_class br_cc(Universe br, cmpOp cmp, flagsReg cr, label labl) %{ 3364 single_instruction_with_delay_slot; 3365 cr : E(read); 3366 BR : R; 3367%} 3368 3369pipe_class br_reg(Universe br, cmpOp cmp, iRegI op1, label labl) %{ 3370 single_instruction_with_delay_slot; 3371 op1 : E(read); 3372 BR : R; 3373 MS : R; 3374%} 3375 3376pipe_class br_nop() %{ 3377 single_instruction; 3378 BR : R; 3379%} 3380 3381pipe_class simple_call(method meth) %{ 3382 instruction_count(2); multiple_bundles; force_serialization; 3383 fixed_latency(100); 3384 BR : R(1); 3385 MS : R(1); 3386 A0 : R(1); 3387%} 3388 3389pipe_class compiled_call(method meth) %{ 3390 instruction_count(1); multiple_bundles; force_serialization; 3391 fixed_latency(100); 3392 MS : R(1); 3393%} 3394 3395pipe_class call(method meth) %{ 3396 instruction_count(0); multiple_bundles; force_serialization; 3397 fixed_latency(100); 3398%} 3399 3400pipe_class tail_call(Universe ignore, label labl) %{ 3401 single_instruction; has_delay_slot; 3402 fixed_latency(100); 3403 BR : R(1); 3404 MS : R(1); 3405%} 3406 3407pipe_class ret(Universe ignore) %{ 3408 single_instruction; has_delay_slot; 3409 BR : R(1); 3410 MS : R(1); 3411%} 3412 3413// The real do-nothing guy 3414pipe_class empty( ) %{ 3415 instruction_count(0); 3416%} 3417 3418pipe_class long_memory_op() %{ 3419 instruction_count(0); multiple_bundles; force_serialization; 3420 fixed_latency(25); 3421 MS : R(1); 3422%} 3423 3424// Check-cast 3425pipe_class partial_subtype_check_pipe(Universe ignore, iRegP array, iRegP match ) %{ 3426 array : R(read); 3427 match : R(read); 3428 IALU : R(2); 3429 BR : R(2); 3430 MS : R; 3431%} 3432 3433// Convert FPU flags into +1,0,-1 3434pipe_class floating_cmp( iRegI dst, regF src1, regF src2 ) %{ 3435 src1 : E(read); 3436 src2 : E(read); 3437 dst : E(write); 3438 FA : R; 3439 MS : R(2); 3440 BR : R(2); 3441%} 3442 3443// Compare for p < q, and conditionally add y 3444pipe_class cadd_cmpltmask( iRegI p, iRegI q, iRegI y ) %{ 3445 p : E(read); 3446 q : E(read); 3447 y : E(read); 3448 IALU : R(3) 3449%} 3450 3451// Perform a compare, then move conditionally in a branch delay slot. 3452pipe_class min_max( iRegI src2, iRegI srcdst ) %{ 3453 src2 : E(read); 3454 srcdst : E(read); 3455 IALU : R; 3456 BR : R; 3457%} 3458 3459// Define the class for the Nop node 3460define %{ 3461 MachNop = ialu_nop; 3462%} 3463 3464%} 3465 3466//----------INSTRUCTIONS------------------------------------------------------- 3467 3468//------------Special Nop instructions for bundling - no match rules----------- 3469// Nop using the A0 functional unit 3470instruct Nop_A0() %{ 3471 ins_pipe(ialu_nop_A0); 3472%} 3473 3474// Nop using the A1 functional unit 3475instruct Nop_A1( ) %{ 3476 ins_pipe(ialu_nop_A1); 3477%} 3478 3479// Nop using the memory functional unit 3480instruct Nop_MS( ) %{ 3481 ins_pipe(mem_nop); 3482%} 3483 3484// Nop using the floating add functional unit 3485instruct Nop_FA( ) %{ 3486 ins_pipe(fadd_nop); 3487%} 3488 3489// Nop using the branch functional unit 3490instruct Nop_BR( ) %{ 3491 ins_pipe(br_nop); 3492%} 3493 3494//----------Load/Store/Move Instructions--------------------------------------- 3495//----------Load Instructions-------------------------------------------------- 3496// Load Byte (8bit signed) 3497instruct loadB(iRegI dst, memoryB mem) %{ 3498 match(Set dst (LoadB mem)); 3499 ins_cost(MEMORY_REF_COST); 3500 3501 size(4); 3502 format %{ "LDRSB $dst,$mem\t! byte -> int" %} 3503 ins_encode %{ 3504 __ ldrsb($dst$$Register, $mem$$Address); 3505 %} 3506 ins_pipe(iload_mask_mem); 3507%} 3508 3509// Load Byte (8bit signed) into a Long Register 3510instruct loadB2L(iRegL dst, memoryB mem) %{ 3511 match(Set dst (ConvI2L (LoadB mem))); 3512 ins_cost(MEMORY_REF_COST); 3513 3514 size(8); 3515 format %{ "LDRSB $dst.lo,$mem\t! byte -> long\n\t" 3516 "ASR $dst.hi,$dst.lo,31" %} 3517 ins_encode %{ 3518 __ ldrsb($dst$$Register, $mem$$Address); 3519 __ mov($dst$$Register->successor(), AsmOperand($dst$$Register, asr, 31)); 3520 %} 3521 ins_pipe(iload_mask_mem); 3522%} 3523 3524// Load Unsigned Byte (8bit UNsigned) into an int reg 3525instruct loadUB(iRegI dst, memoryB mem) %{ 3526 match(Set dst (LoadUB mem)); 3527 ins_cost(MEMORY_REF_COST); 3528 3529 size(4); 3530 format %{ "LDRB $dst,$mem\t! ubyte -> int" %} 3531 ins_encode %{ 3532 __ ldrb($dst$$Register, $mem$$Address); 3533 %} 3534 ins_pipe(iload_mem); 3535%} 3536 3537// Load Unsigned Byte (8bit UNsigned) into a Long Register 3538instruct loadUB2L(iRegL dst, memoryB mem) %{ 3539 match(Set dst (ConvI2L (LoadUB mem))); 3540 ins_cost(MEMORY_REF_COST); 3541 3542 size(8); 3543 format %{ "LDRB $dst.lo,$mem\t! ubyte -> long\n\t" 3544 "MOV $dst.hi,0" %} 3545 ins_encode %{ 3546 __ ldrb($dst$$Register, $mem$$Address); 3547 __ mov($dst$$Register->successor(), 0); 3548 %} 3549 ins_pipe(iload_mem); 3550%} 3551 3552// Load Unsigned Byte (8 bit UNsigned) with immediate mask into Long Register 3553instruct loadUB2L_limmI(iRegL dst, memoryB mem, limmIlow8 mask) %{ 3554 match(Set dst (ConvI2L (AndI (LoadUB mem) mask))); 3555 3556 ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST); 3557 size(12); 3558 format %{ "LDRB $dst.lo,$mem\t! ubyte -> long\n\t" 3559 "MOV $dst.hi,0\n\t" 3560 "AND $dst.lo,$dst.lo,$mask" %} 3561 ins_encode %{ 3562 __ ldrb($dst$$Register, $mem$$Address); 3563 __ mov($dst$$Register->successor(), 0); 3564 __ andr($dst$$Register, $dst$$Register, limmI_low($mask$$constant, 8)); 3565 %} 3566 ins_pipe(iload_mem); 3567%} 3568 3569// Load Short (16bit signed) 3570 3571instruct loadS(iRegI dst, memoryS mem) %{ 3572 match(Set dst (LoadS mem)); 3573 ins_cost(MEMORY_REF_COST); 3574 3575 size(4); 3576 format %{ "LDRSH $dst,$mem\t! short" %} 3577 ins_encode %{ 3578 __ ldrsh($dst$$Register, $mem$$Address); 3579 %} 3580 ins_pipe(iload_mask_mem); 3581%} 3582 3583// Load Short (16 bit signed) to Byte (8 bit signed) 3584instruct loadS2B(iRegI dst, memoryS mem, immI_24 twentyfour) %{ 3585 match(Set dst (RShiftI (LShiftI (LoadS mem) twentyfour) twentyfour)); 3586 ins_cost(MEMORY_REF_COST); 3587 3588 size(4); 3589 3590 format %{ "LDRSB $dst,$mem\t! short -> byte" %} 3591 ins_encode %{ 3592 __ ldrsb($dst$$Register, $mem$$Address); 3593 %} 3594 ins_pipe(iload_mask_mem); 3595%} 3596 3597// Load Short (16bit signed) into a Long Register 3598instruct loadS2L(iRegL dst, memoryS mem) %{ 3599 match(Set dst (ConvI2L (LoadS mem))); 3600 ins_cost(MEMORY_REF_COST); 3601 3602 size(8); 3603 format %{ "LDRSH $dst.lo,$mem\t! short -> long\n\t" 3604 "ASR $dst.hi,$dst.lo,31" %} 3605 ins_encode %{ 3606 __ ldrsh($dst$$Register, $mem$$Address); 3607 __ mov($dst$$Register->successor(), AsmOperand($dst$$Register, asr, 31)); 3608 %} 3609 ins_pipe(iload_mask_mem); 3610%} 3611 3612// Load Unsigned Short/Char (16bit UNsigned) 3613 3614 3615instruct loadUS(iRegI dst, memoryS mem) %{ 3616 match(Set dst (LoadUS mem)); 3617 ins_cost(MEMORY_REF_COST); 3618 3619 size(4); 3620 format %{ "LDRH $dst,$mem\t! ushort/char" %} 3621 ins_encode %{ 3622 __ ldrh($dst$$Register, $mem$$Address); 3623 %} 3624 ins_pipe(iload_mem); 3625%} 3626 3627// Load Unsigned Short/Char (16 bit UNsigned) to Byte (8 bit signed) 3628instruct loadUS2B(iRegI dst, memoryB mem, immI_24 twentyfour) %{ 3629 match(Set dst (RShiftI (LShiftI (LoadUS mem) twentyfour) twentyfour)); 3630 ins_cost(MEMORY_REF_COST); 3631 3632 size(4); 3633 format %{ "LDRSB $dst,$mem\t! ushort -> byte" %} 3634 ins_encode %{ 3635 __ ldrsb($dst$$Register, $mem$$Address); 3636 %} 3637 ins_pipe(iload_mask_mem); 3638%} 3639 3640// Load Unsigned Short/Char (16bit UNsigned) into a Long Register 3641instruct loadUS2L(iRegL dst, memoryS mem) %{ 3642 match(Set dst (ConvI2L (LoadUS mem))); 3643 ins_cost(MEMORY_REF_COST); 3644 3645 size(8); 3646 format %{ "LDRH $dst.lo,$mem\t! short -> long\n\t" 3647 "MOV $dst.hi, 0" %} 3648 ins_encode %{ 3649 __ ldrh($dst$$Register, $mem$$Address); 3650 __ mov($dst$$Register->successor(), 0); 3651 %} 3652 ins_pipe(iload_mem); 3653%} 3654 3655// Load Unsigned Short/Char (16bit UNsigned) with mask 0xFF into a Long Register 3656instruct loadUS2L_immI_255(iRegL dst, memoryB mem, immI_255 mask) %{ 3657 match(Set dst (ConvI2L (AndI (LoadUS mem) mask))); 3658 ins_cost(MEMORY_REF_COST); 3659 3660 size(8); 3661 format %{ "LDRB $dst.lo,$mem\t! \n\t" 3662 "MOV $dst.hi, 0" %} 3663 ins_encode %{ 3664 __ ldrb($dst$$Register, $mem$$Address); 3665 __ mov($dst$$Register->successor(), 0); 3666 %} 3667 ins_pipe(iload_mem); 3668%} 3669 3670// Load Unsigned Short/Char (16bit UNsigned) with a immediate mask into a Long Register 3671instruct loadUS2L_limmI(iRegL dst, memoryS mem, limmI mask) %{ 3672 match(Set dst (ConvI2L (AndI (LoadUS mem) mask))); 3673 ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST); 3674 3675 size(12); 3676 format %{ "LDRH $dst,$mem\t! ushort/char & mask -> long\n\t" 3677 "MOV $dst.hi, 0\n\t" 3678 "AND $dst,$dst,$mask" %} 3679 ins_encode %{ 3680 __ ldrh($dst$$Register, $mem$$Address); 3681 __ mov($dst$$Register->successor(), 0); 3682 __ andr($dst$$Register, $dst$$Register, $mask$$constant); 3683 %} 3684 ins_pipe(iload_mem); 3685%} 3686 3687// Load Integer 3688 3689 3690instruct loadI(iRegI dst, memoryI mem) %{ 3691 match(Set dst (LoadI mem)); 3692 ins_cost(MEMORY_REF_COST); 3693 3694 size(4); 3695 format %{ "ldr_s32 $dst,$mem\t! int" %} 3696 ins_encode %{ 3697 __ ldr_s32($dst$$Register, $mem$$Address); 3698 %} 3699 ins_pipe(iload_mem); 3700%} 3701 3702// Load Integer to Byte (8 bit signed) 3703instruct loadI2B(iRegI dst, memoryS mem, immI_24 twentyfour) %{ 3704 match(Set dst (RShiftI (LShiftI (LoadI mem) twentyfour) twentyfour)); 3705 ins_cost(MEMORY_REF_COST); 3706 3707 size(4); 3708 3709 format %{ "LDRSB $dst,$mem\t! int -> byte" %} 3710 ins_encode %{ 3711 __ ldrsb($dst$$Register, $mem$$Address); 3712 %} 3713 ins_pipe(iload_mask_mem); 3714%} 3715 3716// Load Integer to Unsigned Byte (8 bit UNsigned) 3717instruct loadI2UB(iRegI dst, memoryB mem, immI_255 mask) %{ 3718 match(Set dst (AndI (LoadI mem) mask)); 3719 ins_cost(MEMORY_REF_COST); 3720 3721 size(4); 3722 3723 format %{ "LDRB $dst,$mem\t! int -> ubyte" %} 3724 ins_encode %{ 3725 __ ldrb($dst$$Register, $mem$$Address); 3726 %} 3727 ins_pipe(iload_mask_mem); 3728%} 3729 3730// Load Integer to Short (16 bit signed) 3731instruct loadI2S(iRegI dst, memoryS mem, immI_16 sixteen) %{ 3732 match(Set dst (RShiftI (LShiftI (LoadI mem) sixteen) sixteen)); 3733 ins_cost(MEMORY_REF_COST); 3734 3735 size(4); 3736 format %{ "LDRSH $dst,$mem\t! int -> short" %} 3737 ins_encode %{ 3738 __ ldrsh($dst$$Register, $mem$$Address); 3739 %} 3740 ins_pipe(iload_mask_mem); 3741%} 3742 3743// Load Integer to Unsigned Short (16 bit UNsigned) 3744instruct loadI2US(iRegI dst, memoryS mem, immI_65535 mask) %{ 3745 match(Set dst (AndI (LoadI mem) mask)); 3746 ins_cost(MEMORY_REF_COST); 3747 3748 size(4); 3749 format %{ "LDRH $dst,$mem\t! int -> ushort/char" %} 3750 ins_encode %{ 3751 __ ldrh($dst$$Register, $mem$$Address); 3752 %} 3753 ins_pipe(iload_mask_mem); 3754%} 3755 3756// Load Integer into a Long Register 3757instruct loadI2L(iRegL dst, memoryI mem) %{ 3758 match(Set dst (ConvI2L (LoadI mem))); 3759 ins_cost(MEMORY_REF_COST); 3760 3761 size(8); 3762 format %{ "LDR $dst.lo,$mem\t! int -> long\n\t" 3763 "ASR $dst.hi,$dst.lo,31\t! int->long" %} 3764 ins_encode %{ 3765 __ ldr($dst$$Register, $mem$$Address); 3766 __ mov($dst$$Register->successor(), AsmOperand($dst$$Register, asr, 31)); 3767 %} 3768 ins_pipe(iload_mask_mem); 3769%} 3770 3771// Load Integer with mask 0xFF into a Long Register 3772instruct loadI2L_immI_255(iRegL dst, memoryB mem, immI_255 mask) %{ 3773 match(Set dst (ConvI2L (AndI (LoadI mem) mask))); 3774 ins_cost(MEMORY_REF_COST); 3775 3776 size(8); 3777 format %{ "LDRB $dst.lo,$mem\t! int & 0xFF -> long\n\t" 3778 "MOV $dst.hi, 0" %} 3779 ins_encode %{ 3780 __ ldrb($dst$$Register, $mem$$Address); 3781 __ mov($dst$$Register->successor(), 0); 3782 %} 3783 ins_pipe(iload_mem); 3784%} 3785 3786// Load Integer with mask 0xFFFF into a Long Register 3787instruct loadI2L_immI_65535(iRegL dst, memoryS mem, immI_65535 mask) %{ 3788 match(Set dst (ConvI2L (AndI (LoadI mem) mask))); 3789 ins_cost(MEMORY_REF_COST); 3790 3791 size(8); 3792 format %{ "LDRH $dst,$mem\t! int & 0xFFFF -> long\n\t" 3793 "MOV $dst.hi, 0" %} 3794 ins_encode %{ 3795 __ ldrh($dst$$Register, $mem$$Address); 3796 __ mov($dst$$Register->successor(), 0); 3797 %} 3798 ins_pipe(iload_mask_mem); 3799%} 3800 3801// Load Integer with a 31-bit immediate mask into a Long Register 3802instruct loadI2L_limmU31(iRegL dst, memoryI mem, limmU31 mask) %{ 3803 match(Set dst (ConvI2L (AndI (LoadI mem) mask))); 3804 ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST); 3805 3806 size(12); 3807 format %{ "LDR $dst.lo,$mem\t! int -> long\n\t" 3808 "MOV $dst.hi, 0\n\t" 3809 "AND $dst,$dst,$mask" %} 3810 3811 ins_encode %{ 3812 __ ldr($dst$$Register, $mem$$Address); 3813 __ mov($dst$$Register->successor(), 0); 3814 __ andr($dst$$Register, $dst$$Register, $mask$$constant); 3815 %} 3816 ins_pipe(iload_mem); 3817%} 3818 3819// Load Integer with a 31-bit mask into a Long Register 3820// FIXME: use iRegI mask, remove tmp? 3821instruct loadI2L_immU31(iRegL dst, memoryI mem, immU31 mask, iRegI tmp) %{ 3822 match(Set dst (ConvI2L (AndI (LoadI mem) mask))); 3823 effect(TEMP dst, TEMP tmp); 3824 3825 ins_cost(MEMORY_REF_COST + 4*DEFAULT_COST); 3826 size(20); 3827 format %{ "LDR $mem,$dst\t! int & 31-bit mask -> long\n\t" 3828 "MOV $dst.hi, 0\n\t" 3829 "MOV_SLOW $tmp,$mask\n\t" 3830 "AND $dst,$tmp,$dst" %} 3831 ins_encode %{ 3832 __ ldr($dst$$Register, $mem$$Address); 3833 __ mov($dst$$Register->successor(), 0); 3834 __ mov_slow($tmp$$Register, $mask$$constant); 3835 __ andr($dst$$Register, $dst$$Register, $tmp$$Register); 3836 %} 3837 ins_pipe(iload_mem); 3838%} 3839 3840// Load Unsigned Integer into a Long Register 3841instruct loadUI2L(iRegL dst, memoryI mem, immL_32bits mask) %{ 3842 match(Set dst (AndL (ConvI2L (LoadI mem)) mask)); 3843 ins_cost(MEMORY_REF_COST); 3844 3845 size(8); 3846 format %{ "LDR $dst.lo,$mem\t! uint -> long\n\t" 3847 "MOV $dst.hi,0" %} 3848 ins_encode %{ 3849 __ ldr($dst$$Register, $mem$$Address); 3850 __ mov($dst$$Register->successor(), 0); 3851 %} 3852 ins_pipe(iload_mem); 3853%} 3854 3855// Load Long 3856 3857 3858instruct loadL(iRegLd dst, memoryL mem ) %{ 3859 predicate(!((LoadLNode*)n)->require_atomic_access()); 3860 match(Set dst (LoadL mem)); 3861 effect(TEMP dst); 3862 ins_cost(MEMORY_REF_COST); 3863 3864 size(4); 3865 format %{ "ldr_64 $dst,$mem\t! long" %} 3866 ins_encode %{ 3867 __ ldr_64($dst$$Register, $mem$$Address); 3868 %} 3869 ins_pipe(iload_mem); 3870%} 3871 3872instruct loadL_2instr(iRegL dst, memorylong mem ) %{ 3873 predicate(!((LoadLNode*)n)->require_atomic_access()); 3874 match(Set dst (LoadL mem)); 3875 ins_cost(MEMORY_REF_COST + DEFAULT_COST); 3876 3877 size(8); 3878 format %{ "LDR $dst.lo,$mem \t! long order of instrs reversed if $dst.lo == base($mem)\n\t" 3879 "LDR $dst.hi,$mem+4 or $mem" %} 3880 ins_encode %{ 3881 Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 3882 Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none); 3883 3884 if ($dst$$Register == reg_to_register_object($mem$$base)) { 3885 __ ldr($dst$$Register->successor(), Amemhi); 3886 __ ldr($dst$$Register, Amemlo); 3887 } else { 3888 __ ldr($dst$$Register, Amemlo); 3889 __ ldr($dst$$Register->successor(), Amemhi); 3890 } 3891 %} 3892 ins_pipe(iload_mem); 3893%} 3894 3895instruct loadL_volatile(iRegL dst, indirect mem ) %{ 3896 predicate(((LoadLNode*)n)->require_atomic_access()); 3897 match(Set dst (LoadL mem)); 3898 ins_cost(MEMORY_REF_COST); 3899 3900 size(4); 3901 format %{ "LDMIA $dst,$mem\t! long" %} 3902 ins_encode %{ 3903 // FIXME: why is ldmia considered atomic? Should be ldrexd 3904 RegisterSet set($dst$$Register); 3905 set = set | reg_to_register_object($dst$$reg + 1); 3906 __ ldmia(reg_to_register_object($mem$$base), set); 3907 %} 3908 ins_pipe(iload_mem); 3909%} 3910 3911instruct loadL_volatile_fp(iRegL dst, memoryD mem ) %{ 3912 predicate(((LoadLNode*)n)->require_atomic_access()); 3913 match(Set dst (LoadL mem)); 3914 ins_cost(MEMORY_REF_COST); 3915 3916 size(8); 3917 format %{ "FLDD S14, $mem" 3918 "FMRRD $dst, S14\t! long \n't" %} 3919 ins_encode %{ 3920 __ fldd(S14, $mem$$Address); 3921 __ fmrrd($dst$$Register, $dst$$Register->successor(), S14); 3922 %} 3923 ins_pipe(iload_mem); 3924%} 3925 3926instruct loadL_unaligned(iRegL dst, memorylong mem ) %{ 3927 match(Set dst (LoadL_unaligned mem)); 3928 ins_cost(MEMORY_REF_COST); 3929 3930 size(8); 3931 format %{ "LDR $dst.lo,$mem\t! long order of instrs reversed if $dst.lo == base($mem)\n\t" 3932 "LDR $dst.hi,$mem+4" %} 3933 ins_encode %{ 3934 Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 3935 Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none); 3936 3937 if ($dst$$Register == reg_to_register_object($mem$$base)) { 3938 __ ldr($dst$$Register->successor(), Amemhi); 3939 __ ldr($dst$$Register, Amemlo); 3940 } else { 3941 __ ldr($dst$$Register, Amemlo); 3942 __ ldr($dst$$Register->successor(), Amemhi); 3943 } 3944 %} 3945 ins_pipe(iload_mem); 3946%} 3947 3948// Load Range 3949instruct loadRange(iRegI dst, memoryI mem) %{ 3950 match(Set dst (LoadRange mem)); 3951 ins_cost(MEMORY_REF_COST); 3952 3953 size(4); 3954 format %{ "LDR_u32 $dst,$mem\t! range" %} 3955 ins_encode %{ 3956 __ ldr_u32($dst$$Register, $mem$$Address); 3957 %} 3958 ins_pipe(iload_mem); 3959%} 3960 3961// Load Pointer 3962 3963 3964instruct loadP(iRegP dst, memoryP mem) %{ 3965 match(Set dst (LoadP mem)); 3966 ins_cost(MEMORY_REF_COST); 3967 size(4); 3968 3969 format %{ "LDR $dst,$mem\t! ptr" %} 3970 ins_encode %{ 3971 __ ldr($dst$$Register, $mem$$Address); 3972 %} 3973 ins_pipe(iload_mem); 3974%} 3975 3976#ifdef XXX 3977// FIXME XXXX 3978//instruct loadSP(iRegP dst, memoryP mem) %{ 3979instruct loadSP(SPRegP dst, memoryP mem, iRegP tmp) %{ 3980 match(Set dst (LoadP mem)); 3981 effect(TEMP tmp); 3982 ins_cost(MEMORY_REF_COST+1); 3983 size(8); 3984 3985 format %{ "LDR $tmp,$mem\t! ptr\n\t" 3986 "MOV $dst,$tmp\t! ptr" %} 3987 ins_encode %{ 3988 __ ldr($tmp$$Register, $mem$$Address); 3989 __ mov($dst$$Register, $tmp$$Register); 3990 %} 3991 ins_pipe(iload_mem); 3992%} 3993#endif 3994 3995#ifdef _LP64 3996// Load Compressed Pointer 3997 3998// XXX This variant shouldn't be necessary if 6217251 is implemented 3999instruct loadNoff(iRegN dst, memoryScaledI mem, aimmX off, iRegP tmp) %{ 4000 match(Set dst (LoadN (AddP mem off))); 4001 ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free 4002 effect(TEMP tmp); 4003 size(4 * 2); 4004 4005 format %{ "ldr_u32 $dst,$mem+$off\t! compressed ptr temp=$tmp" %} 4006 ins_encode %{ 4007 Register base = reg_to_register_object($mem$$base); 4008 __ add($tmp$$Register, base, $off$$constant); 4009 Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 4010 __ ldr_u32($dst$$Register, nmem); 4011 %} 4012 ins_pipe(iload_mem); 4013%} 4014 4015instruct loadN(iRegN dst, memoryI mem) %{ 4016 match(Set dst (LoadN mem)); 4017 ins_cost(MEMORY_REF_COST); 4018 size(4); 4019 4020 format %{ "ldr_u32 $dst,$mem\t! compressed ptr" %} 4021 ins_encode %{ 4022 __ ldr_u32($dst$$Register, $mem$$Address); 4023 %} 4024 ins_pipe(iload_mem); 4025%} 4026#endif 4027 4028// Load Klass Pointer 4029instruct loadKlass(iRegP dst, memoryI mem) %{ 4030 match(Set dst (LoadKlass mem)); 4031 ins_cost(MEMORY_REF_COST); 4032 size(4); 4033 4034 format %{ "LDR $dst,$mem\t! klass ptr" %} 4035 ins_encode %{ 4036 __ ldr($dst$$Register, $mem$$Address); 4037 %} 4038 ins_pipe(iload_mem); 4039%} 4040 4041#ifdef _LP64 4042// Load narrow Klass Pointer 4043instruct loadNKlass(iRegN dst, memoryI mem) %{ 4044 match(Set dst (LoadNKlass mem)); 4045 ins_cost(MEMORY_REF_COST); 4046 size(4); 4047 4048 format %{ "ldr_u32 $dst,$mem\t! compressed klass ptr" %} 4049 ins_encode %{ 4050 __ ldr_u32($dst$$Register, $mem$$Address); 4051 %} 4052 ins_pipe(iload_mem); 4053%} 4054#endif 4055 4056 4057instruct loadD(regD dst, memoryD mem) %{ 4058 match(Set dst (LoadD mem)); 4059 ins_cost(MEMORY_REF_COST); 4060 4061 size(4); 4062 // FIXME: needs to be atomic, but ARMv7 A.R.M. guarantees 4063 // only LDREXD and STREXD are 64-bit single-copy atomic 4064 format %{ "FLDD $dst,$mem" %} 4065 ins_encode %{ 4066 __ ldr_double($dst$$FloatRegister, $mem$$Address); 4067 %} 4068 ins_pipe(floadD_mem); 4069%} 4070 4071// Load Double - UNaligned 4072instruct loadD_unaligned(regD_low dst, memoryF2 mem ) %{ 4073 match(Set dst (LoadD_unaligned mem)); 4074 ins_cost(MEMORY_REF_COST*2+DEFAULT_COST); 4075 size(8); 4076 format %{ "FLDS $dst.lo,$mem\t! misaligned double\n" 4077 "\tFLDS $dst.hi,$mem+4\t!" %} 4078 ins_encode %{ 4079 Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 4080 Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none); 4081 __ flds($dst$$FloatRegister, Amemlo); 4082 __ flds($dst$$FloatRegister->successor(), Amemhi); 4083 %} 4084 ins_pipe(iload_mem); 4085%} 4086 4087 4088instruct loadF(regF dst, memoryF mem) %{ 4089 match(Set dst (LoadF mem)); 4090 4091 ins_cost(MEMORY_REF_COST); 4092 size(4); 4093 format %{ "FLDS $dst,$mem" %} 4094 ins_encode %{ 4095 __ ldr_float($dst$$FloatRegister, $mem$$Address); 4096 %} 4097 ins_pipe(floadF_mem); 4098%} 4099 4100 4101// // Load Constant 4102instruct loadConI( iRegI dst, immI src ) %{ 4103 match(Set dst src); 4104 ins_cost(DEFAULT_COST * 3/2); 4105 format %{ "MOV_SLOW $dst, $src" %} 4106 ins_encode %{ 4107 __ mov_slow($dst$$Register, $src$$constant); 4108 %} 4109 ins_pipe(ialu_hi_lo_reg); 4110%} 4111 4112instruct loadConIMov( iRegI dst, immIMov src ) %{ 4113 match(Set dst src); 4114 size(4); 4115 format %{ "MOV $dst, $src" %} 4116 ins_encode %{ 4117 __ mov($dst$$Register, $src$$constant); 4118 %} 4119 ins_pipe(ialu_imm); 4120%} 4121 4122instruct loadConIMovn( iRegI dst, immIRotn src ) %{ 4123 match(Set dst src); 4124 size(4); 4125 format %{ "MVN $dst, ~$src" %} 4126 ins_encode %{ 4127 __ mvn($dst$$Register, ~$src$$constant); 4128 %} 4129 ins_pipe(ialu_imm_n); 4130%} 4131 4132instruct loadConI16( iRegI dst, immI16 src ) %{ 4133 match(Set dst src); 4134 size(4); 4135 format %{ "MOVW $dst, $src" %} 4136 ins_encode %{ 4137 __ movw($dst$$Register, $src$$constant); 4138 %} 4139 ins_pipe(ialu_imm_n); 4140%} 4141 4142instruct loadConP(iRegP dst, immP src) %{ 4143 match(Set dst src); 4144 ins_cost(DEFAULT_COST * 3/2); 4145 format %{ "MOV_SLOW $dst,$src\t!ptr" %} 4146 ins_encode %{ 4147 relocInfo::relocType constant_reloc = _opnds[1]->constant_reloc(); 4148 intptr_t val = $src$$constant; 4149 if (constant_reloc == relocInfo::oop_type) { 4150 __ mov_oop($dst$$Register, (jobject)val); 4151 } else if (constant_reloc == relocInfo::metadata_type) { 4152 __ mov_metadata($dst$$Register, (Metadata*)val); 4153 } else { 4154 __ mov_slow($dst$$Register, val); 4155 } 4156 %} 4157 ins_pipe(loadConP); 4158%} 4159 4160 4161instruct loadConL(iRegL dst, immL src) %{ 4162 match(Set dst src); 4163 ins_cost(DEFAULT_COST * 4); 4164 format %{ "MOV_SLOW $dst.lo, $src & 0x0FFFFFFFFL \t! long\n\t" 4165 "MOV_SLOW $dst.hi, $src >> 32" %} 4166 ins_encode %{ 4167 __ mov_slow(reg_to_register_object($dst$$reg), $src$$constant & 0x0FFFFFFFFL); 4168 __ mov_slow(reg_to_register_object($dst$$reg + 1), ((julong)($src$$constant)) >> 32); 4169 %} 4170 ins_pipe(loadConL); 4171%} 4172 4173instruct loadConL16( iRegL dst, immL16 src ) %{ 4174 match(Set dst src); 4175 ins_cost(DEFAULT_COST * 2); 4176 4177 size(8); 4178 format %{ "MOVW $dst.lo, $src \n\t" 4179 "MOVW $dst.hi, 0 \n\t" %} 4180 ins_encode %{ 4181 __ movw($dst$$Register, $src$$constant); 4182 __ movw($dst$$Register->successor(), 0); 4183 %} 4184 ins_pipe(ialu_imm); 4185%} 4186 4187instruct loadConF_imm8(regF dst, imm8F src) %{ 4188 match(Set dst src); 4189 ins_cost(DEFAULT_COST); 4190 size(4); 4191 4192 format %{ "FCONSTS $dst, $src"%} 4193 4194 ins_encode %{ 4195 __ fconsts($dst$$FloatRegister, Assembler::float_num($src$$constant).imm8()); 4196 %} 4197 ins_pipe(loadConFD); // FIXME 4198%} 4199 4200 4201instruct loadConF(regF dst, immF src, iRegI tmp) %{ 4202 match(Set dst src); 4203 ins_cost(DEFAULT_COST * 2); 4204 effect(TEMP tmp); 4205 size(3*4); 4206 4207 format %{ "MOV_SLOW $tmp, $src\n\t" 4208 "FMSR $dst, $tmp"%} 4209 4210 ins_encode %{ 4211 // FIXME revisit once 6961697 is in 4212 union { 4213 jfloat f; 4214 int i; 4215 } v; 4216 v.f = $src$$constant; 4217 __ mov_slow($tmp$$Register, v.i); 4218 __ fmsr($dst$$FloatRegister, $tmp$$Register); 4219 %} 4220 ins_pipe(loadConFD); // FIXME 4221%} 4222 4223instruct loadConD_imm8(regD dst, imm8D src) %{ 4224 match(Set dst src); 4225 ins_cost(DEFAULT_COST); 4226 size(4); 4227 4228 format %{ "FCONSTD $dst, $src"%} 4229 4230 ins_encode %{ 4231 __ fconstd($dst$$FloatRegister, Assembler::double_num($src$$constant).imm8()); 4232 %} 4233 ins_pipe(loadConFD); // FIXME 4234%} 4235 4236instruct loadConD(regD dst, immD src, iRegP tmp) %{ 4237 match(Set dst src); 4238 effect(TEMP tmp); 4239 ins_cost(MEMORY_REF_COST); 4240 format %{ "FLDD $dst, [$constanttablebase + $constantoffset]\t! load from constant table: double=$src" %} 4241 4242 ins_encode %{ 4243 Register r = $constanttablebase; 4244 int offset = $constantoffset($src); 4245 if (!is_memoryD(offset)) { // can't use a predicate 4246 // in load constant instructs 4247 __ add_slow($tmp$$Register, r, offset); 4248 r = $tmp$$Register; 4249 offset = 0; 4250 } 4251 __ ldr_double($dst$$FloatRegister, Address(r, offset)); 4252 %} 4253 ins_pipe(loadConFD); 4254%} 4255 4256// Prefetch instructions. 4257// Must be safe to execute with invalid address (cannot fault). 4258 4259instruct prefetchAlloc_mp( memoryP mem ) %{ 4260 predicate(VM_Version::has_multiprocessing_extensions()); 4261 match( PrefetchAllocation mem ); 4262 ins_cost(MEMORY_REF_COST); 4263 size(4); 4264 4265 format %{ "PLDW $mem\t! Prefetch allocation" %} 4266 ins_encode %{ 4267 __ pldw($mem$$Address); 4268 %} 4269 ins_pipe(iload_mem); 4270%} 4271 4272instruct prefetchAlloc_sp( memoryP mem ) %{ 4273 predicate(!VM_Version::has_multiprocessing_extensions()); 4274 match( PrefetchAllocation mem ); 4275 ins_cost(MEMORY_REF_COST); 4276 size(4); 4277 4278 format %{ "PLD $mem\t! Prefetch allocation" %} 4279 ins_encode %{ 4280 __ pld($mem$$Address); 4281 %} 4282 ins_pipe(iload_mem); 4283%} 4284 4285 4286//----------Store Instructions------------------------------------------------- 4287// Store Byte 4288instruct storeB(memoryB mem, store_RegI src) %{ 4289 match(Set mem (StoreB mem src)); 4290 ins_cost(MEMORY_REF_COST); 4291 4292 size(4); 4293 format %{ "STRB $src,$mem\t! byte" %} 4294 ins_encode %{ 4295 __ strb($src$$Register, $mem$$Address); 4296 %} 4297 ins_pipe(istore_mem_reg); 4298%} 4299 4300instruct storeCM(memoryB mem, store_RegI src) %{ 4301 match(Set mem (StoreCM mem src)); 4302 ins_cost(MEMORY_REF_COST); 4303 4304 size(4); 4305 format %{ "STRB $src,$mem\t! CMS card-mark byte" %} 4306 ins_encode %{ 4307 __ strb($src$$Register, $mem$$Address); 4308 %} 4309 ins_pipe(istore_mem_reg); 4310%} 4311 4312// Store Char/Short 4313 4314 4315instruct storeC(memoryS mem, store_RegI src) %{ 4316 match(Set mem (StoreC mem src)); 4317 ins_cost(MEMORY_REF_COST); 4318 4319 size(4); 4320 format %{ "STRH $src,$mem\t! short" %} 4321 ins_encode %{ 4322 __ strh($src$$Register, $mem$$Address); 4323 %} 4324 ins_pipe(istore_mem_reg); 4325%} 4326 4327// Store Integer 4328 4329 4330instruct storeI(memoryI mem, store_RegI src) %{ 4331 match(Set mem (StoreI mem src)); 4332 ins_cost(MEMORY_REF_COST); 4333 4334 size(4); 4335 format %{ "str_32 $src,$mem" %} 4336 ins_encode %{ 4337 __ str_32($src$$Register, $mem$$Address); 4338 %} 4339 ins_pipe(istore_mem_reg); 4340%} 4341 4342// Store Long 4343 4344 4345instruct storeL(memoryL mem, store_RegLd src) %{ 4346 predicate(!((StoreLNode*)n)->require_atomic_access()); 4347 match(Set mem (StoreL mem src)); 4348 ins_cost(MEMORY_REF_COST); 4349 4350 size(4); 4351 format %{ "str_64 $src,$mem\t! long\n\t" %} 4352 4353 ins_encode %{ 4354 __ str_64($src$$Register, $mem$$Address); 4355 %} 4356 ins_pipe(istore_mem_reg); 4357%} 4358 4359instruct storeL_2instr(memorylong mem, iRegL src) %{ 4360 predicate(!((StoreLNode*)n)->require_atomic_access()); 4361 match(Set mem (StoreL mem src)); 4362 ins_cost(MEMORY_REF_COST + DEFAULT_COST); 4363 4364 size(8); 4365 format %{ "STR $src.lo,$mem\t! long\n\t" 4366 "STR $src.hi,$mem+4" %} 4367 4368 ins_encode %{ 4369 Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 4370 Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none); 4371 __ str($src$$Register, Amemlo); 4372 __ str($src$$Register->successor(), Amemhi); 4373 %} 4374 ins_pipe(istore_mem_reg); 4375%} 4376 4377instruct storeL_volatile(indirect mem, iRegL src) %{ 4378 predicate(((StoreLNode*)n)->require_atomic_access()); 4379 match(Set mem (StoreL mem src)); 4380 ins_cost(MEMORY_REF_COST); 4381 size(4); 4382 format %{ "STMIA $src,$mem\t! long" %} 4383 ins_encode %{ 4384 // FIXME: why is stmia considered atomic? Should be strexd 4385 RegisterSet set($src$$Register); 4386 set = set | reg_to_register_object($src$$reg + 1); 4387 __ stmia(reg_to_register_object($mem$$base), set); 4388 %} 4389 ins_pipe(istore_mem_reg); 4390%} 4391 4392instruct storeL_volatile_fp(memoryD mem, iRegL src) %{ 4393 predicate(((StoreLNode*)n)->require_atomic_access()); 4394 match(Set mem (StoreL mem src)); 4395 ins_cost(MEMORY_REF_COST); 4396 size(8); 4397 format %{ "FMDRR S14, $src\t! long \n\t" 4398 "FSTD S14, $mem" %} 4399 ins_encode %{ 4400 __ fmdrr(S14, $src$$Register, $src$$Register->successor()); 4401 __ fstd(S14, $mem$$Address); 4402 %} 4403 ins_pipe(istore_mem_reg); 4404%} 4405 4406#ifdef XXX 4407// Move SP Pointer 4408//instruct movSP(sp_ptr_RegP dst, SPRegP src) %{ 4409//instruct movSP(iRegP dst, SPRegP src) %{ 4410instruct movSP(store_ptr_RegP dst, SPRegP src) %{ 4411 match(Set dst src); 4412//predicate(!_kids[1]->_leaf->is_Proj() || _kids[1]->_leaf->as_Proj()->_con == TypeFunc::FramePtr); 4413 ins_cost(MEMORY_REF_COST); 4414 size(4); 4415 4416 format %{ "MOV $dst,$src\t! SP ptr\n\t" %} 4417 ins_encode %{ 4418 assert(false, "XXX1 got here"); 4419 __ mov($dst$$Register, SP); 4420 __ mov($dst$$Register, $src$$Register); 4421 %} 4422 ins_pipe(ialu_reg); 4423%} 4424#endif 4425 4426 4427// Store Pointer 4428 4429 4430instruct storeP(memoryP mem, store_ptr_RegP src) %{ 4431 match(Set mem (StoreP mem src)); 4432 ins_cost(MEMORY_REF_COST); 4433 size(4); 4434 4435 format %{ "STR $src,$mem\t! ptr" %} 4436 ins_encode %{ 4437 __ str($src$$Register, $mem$$Address); 4438 %} 4439 ins_pipe(istore_mem_spORreg); 4440%} 4441 4442 4443#ifdef _LP64 4444// Store Compressed Pointer 4445 4446 4447instruct storeN(memoryI mem, store_RegN src) %{ 4448 match(Set mem (StoreN mem src)); 4449 ins_cost(MEMORY_REF_COST); 4450 size(4); 4451 4452 format %{ "str_32 $src,$mem\t! compressed ptr" %} 4453 ins_encode %{ 4454 __ str_32($src$$Register, $mem$$Address); 4455 %} 4456 ins_pipe(istore_mem_reg); 4457%} 4458 4459 4460// Store Compressed Klass Pointer 4461instruct storeNKlass(memoryI mem, store_RegN src) %{ 4462 match(Set mem (StoreNKlass mem src)); 4463 ins_cost(MEMORY_REF_COST); 4464 size(4); 4465 4466 format %{ "str_32 $src,$mem\t! compressed klass ptr" %} 4467 ins_encode %{ 4468 __ str_32($src$$Register, $mem$$Address); 4469 %} 4470 ins_pipe(istore_mem_reg); 4471%} 4472#endif 4473 4474// Store Double 4475 4476 4477instruct storeD(memoryD mem, regD src) %{ 4478 match(Set mem (StoreD mem src)); 4479 ins_cost(MEMORY_REF_COST); 4480 4481 size(4); 4482 // FIXME: needs to be atomic, but ARMv7 A.R.M. guarantees 4483 // only LDREXD and STREXD are 64-bit single-copy atomic 4484 format %{ "FSTD $src,$mem" %} 4485 ins_encode %{ 4486 __ str_double($src$$FloatRegister, $mem$$Address); 4487 %} 4488 ins_pipe(fstoreD_mem_reg); 4489%} 4490 4491 4492// Store Float 4493 4494 4495instruct storeF( memoryF mem, regF src) %{ 4496 match(Set mem (StoreF mem src)); 4497 ins_cost(MEMORY_REF_COST); 4498 4499 size(4); 4500 format %{ "FSTS $src,$mem" %} 4501 ins_encode %{ 4502 __ str_float($src$$FloatRegister, $mem$$Address); 4503 %} 4504 ins_pipe(fstoreF_mem_reg); 4505%} 4506 4507 4508//----------MemBar Instructions----------------------------------------------- 4509// Memory barrier flavors 4510 4511// pattern-match out unnecessary membars 4512instruct membar_storestore() %{ 4513 match(MemBarStoreStore); 4514 ins_cost(4*MEMORY_REF_COST); 4515 4516 size(4); 4517 format %{ "MEMBAR-storestore" %} 4518 ins_encode %{ 4519 __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreStore), noreg); 4520 %} 4521 ins_pipe(long_memory_op); 4522%} 4523 4524instruct membar_acquire() %{ 4525 match(MemBarAcquire); 4526 match(LoadFence); 4527 ins_cost(4*MEMORY_REF_COST); 4528 4529 size(4); 4530 format %{ "MEMBAR-acquire" %} 4531 ins_encode %{ 4532 __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::LoadLoad | MacroAssembler::LoadStore), noreg); 4533 %} 4534 ins_pipe(long_memory_op); 4535%} 4536 4537instruct membar_acquire_lock() %{ 4538 match(MemBarAcquireLock); 4539 ins_cost(0); 4540 4541 size(0); 4542 format %{ "!MEMBAR-acquire (CAS in prior FastLock so empty encoding)" %} 4543 ins_encode( ); 4544 ins_pipe(empty); 4545%} 4546 4547instruct membar_release() %{ 4548 match(MemBarRelease); 4549 match(StoreFence); 4550 ins_cost(4*MEMORY_REF_COST); 4551 4552 size(4); 4553 format %{ "MEMBAR-release" %} 4554 ins_encode %{ 4555 __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreStore | MacroAssembler::LoadStore), noreg); 4556 %} 4557 ins_pipe(long_memory_op); 4558%} 4559 4560instruct membar_release_lock() %{ 4561 match(MemBarReleaseLock); 4562 ins_cost(0); 4563 4564 size(0); 4565 format %{ "!MEMBAR-release (CAS in succeeding FastUnlock so empty encoding)" %} 4566 ins_encode( ); 4567 ins_pipe(empty); 4568%} 4569 4570instruct membar_volatile() %{ 4571 match(MemBarVolatile); 4572 ins_cost(4*MEMORY_REF_COST); 4573 4574 size(4); 4575 format %{ "MEMBAR-volatile" %} 4576 ins_encode %{ 4577 __ membar(MacroAssembler::StoreLoad, noreg); 4578 %} 4579 ins_pipe(long_memory_op); 4580%} 4581 4582instruct unnecessary_membar_volatile() %{ 4583 match(MemBarVolatile); 4584 predicate(Matcher::post_store_load_barrier(n)); 4585 ins_cost(0); 4586 4587 size(0); 4588 format %{ "!MEMBAR-volatile (unnecessary so empty encoding)" %} 4589 ins_encode( ); 4590 ins_pipe(empty); 4591%} 4592 4593//----------Register Move Instructions----------------------------------------- 4594// instruct roundDouble_nop(regD dst) %{ 4595// match(Set dst (RoundDouble dst)); 4596// ins_pipe(empty); 4597// %} 4598 4599 4600// instruct roundFloat_nop(regF dst) %{ 4601// match(Set dst (RoundFloat dst)); 4602// ins_pipe(empty); 4603// %} 4604 4605 4606 4607// Cast Index to Pointer for unsafe natives 4608instruct castX2P(iRegX src, iRegP dst) %{ 4609 match(Set dst (CastX2P src)); 4610 4611 format %{ "MOV $dst,$src\t! IntX->Ptr if $dst != $src" %} 4612 ins_encode %{ 4613 if ($dst$$Register != $src$$Register) { 4614 __ mov($dst$$Register, $src$$Register); 4615 } 4616 %} 4617 ins_pipe(ialu_reg); 4618%} 4619 4620// Cast Pointer to Index for unsafe natives 4621instruct castP2X(iRegP src, iRegX dst) %{ 4622 match(Set dst (CastP2X src)); 4623 4624 format %{ "MOV $dst,$src\t! Ptr->IntX if $dst != $src" %} 4625 ins_encode %{ 4626 if ($dst$$Register != $src$$Register) { 4627 __ mov($dst$$Register, $src$$Register); 4628 } 4629 %} 4630 ins_pipe(ialu_reg); 4631%} 4632 4633//----------Conditional Move--------------------------------------------------- 4634// Conditional move 4635instruct cmovIP_reg(cmpOpP cmp, flagsRegP pcc, iRegI dst, iRegI src) %{ 4636 match(Set dst (CMoveI (Binary cmp pcc) (Binary dst src))); 4637 ins_cost(150); 4638 size(4); 4639 format %{ "MOV$cmp $dst,$src\t! int" %} 4640 ins_encode %{ 4641 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 4642 %} 4643 ins_pipe(ialu_reg); 4644%} 4645 4646 4647instruct cmovIP_immMov(cmpOpP cmp, flagsRegP pcc, iRegI dst, immIMov src) %{ 4648 match(Set dst (CMoveI (Binary cmp pcc) (Binary dst src))); 4649 ins_cost(140); 4650 size(4); 4651 format %{ "MOV$cmp $dst,$src" %} 4652 ins_encode %{ 4653 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 4654 %} 4655 ins_pipe(ialu_imm); 4656%} 4657 4658instruct cmovIP_imm16(cmpOpP cmp, flagsRegP pcc, iRegI dst, immI16 src) %{ 4659 match(Set dst (CMoveI (Binary cmp pcc) (Binary dst src))); 4660 ins_cost(140); 4661 size(4); 4662 format %{ "MOVw$cmp $dst,$src" %} 4663 ins_encode %{ 4664 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 4665 %} 4666 ins_pipe(ialu_imm); 4667%} 4668 4669instruct cmovI_reg(cmpOp cmp, flagsReg icc, iRegI dst, iRegI src) %{ 4670 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 4671 ins_cost(150); 4672 size(4); 4673 format %{ "MOV$cmp $dst,$src" %} 4674 ins_encode %{ 4675 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 4676 %} 4677 ins_pipe(ialu_reg); 4678%} 4679 4680 4681instruct cmovI_immMov(cmpOp cmp, flagsReg icc, iRegI dst, immIMov src) %{ 4682 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 4683 ins_cost(140); 4684 size(4); 4685 format %{ "MOV$cmp $dst,$src" %} 4686 ins_encode %{ 4687 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 4688 %} 4689 ins_pipe(ialu_imm); 4690%} 4691 4692instruct cmovII_imm16(cmpOp cmp, flagsReg icc, iRegI dst, immI16 src) %{ 4693 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 4694 ins_cost(140); 4695 size(4); 4696 format %{ "MOVw$cmp $dst,$src" %} 4697 ins_encode %{ 4698 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 4699 %} 4700 ins_pipe(ialu_imm); 4701%} 4702 4703instruct cmovII_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegI dst, iRegI src) %{ 4704 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 4705 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 4706 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 4707 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 4708 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 4709 ins_cost(150); 4710 size(4); 4711 format %{ "MOV$cmp $dst,$src" %} 4712 ins_encode %{ 4713 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 4714 %} 4715 ins_pipe(ialu_reg); 4716%} 4717 4718instruct cmovII_immMov_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegI dst, immIMov src) %{ 4719 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 4720 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 4721 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 4722 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 4723 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 4724 ins_cost(140); 4725 size(4); 4726 format %{ "MOV$cmp $dst,$src" %} 4727 ins_encode %{ 4728 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 4729 %} 4730 ins_pipe(ialu_imm); 4731%} 4732 4733instruct cmovII_imm16_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegI dst, immI16 src) %{ 4734 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 4735 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 4736 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 4737 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 4738 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 4739 ins_cost(140); 4740 size(4); 4741 format %{ "MOVW$cmp $dst,$src" %} 4742 ins_encode %{ 4743 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 4744 %} 4745 ins_pipe(ialu_imm); 4746%} 4747 4748instruct cmovIIu_reg(cmpOpU cmp, flagsRegU icc, iRegI dst, iRegI src) %{ 4749 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 4750 ins_cost(150); 4751 size(4); 4752 format %{ "MOV$cmp $dst,$src" %} 4753 ins_encode %{ 4754 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 4755 %} 4756 ins_pipe(ialu_reg); 4757%} 4758 4759instruct cmovIIu_immMov(cmpOpU cmp, flagsRegU icc, iRegI dst, immIMov src) %{ 4760 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 4761 ins_cost(140); 4762 size(4); 4763 format %{ "MOV$cmp $dst,$src" %} 4764 ins_encode %{ 4765 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 4766 %} 4767 ins_pipe(ialu_imm); 4768%} 4769 4770instruct cmovIIu_imm16(cmpOpU cmp, flagsRegU icc, iRegI dst, immI16 src) %{ 4771 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 4772 ins_cost(140); 4773 size(4); 4774 format %{ "MOVW$cmp $dst,$src" %} 4775 ins_encode %{ 4776 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 4777 %} 4778 ins_pipe(ialu_imm); 4779%} 4780 4781// Conditional move 4782instruct cmovPP_reg(cmpOpP cmp, flagsRegP pcc, iRegP dst, iRegP src) %{ 4783 match(Set dst (CMoveP (Binary cmp pcc) (Binary dst src))); 4784 ins_cost(150); 4785 size(4); 4786 format %{ "MOV$cmp $dst,$src" %} 4787 ins_encode %{ 4788 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 4789 %} 4790 ins_pipe(ialu_reg); 4791%} 4792 4793instruct cmovPP_imm(cmpOpP cmp, flagsRegP pcc, iRegP dst, immP0 src) %{ 4794 match(Set dst (CMoveP (Binary cmp pcc) (Binary dst src))); 4795 ins_cost(140); 4796 size(4); 4797 format %{ "MOV$cmp $dst,$src" %} 4798 ins_encode %{ 4799 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 4800 %} 4801 ins_pipe(ialu_imm); 4802%} 4803 4804// This instruction also works with CmpN so we don't need cmovPN_reg. 4805instruct cmovPI_reg(cmpOp cmp, flagsReg icc, iRegP dst, iRegP src) %{ 4806 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src))); 4807 ins_cost(150); 4808 4809 size(4); 4810 format %{ "MOV$cmp $dst,$src\t! ptr" %} 4811 ins_encode %{ 4812 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 4813 %} 4814 ins_pipe(ialu_reg); 4815%} 4816 4817instruct cmovPI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegP dst, iRegP src) %{ 4818 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src))); 4819 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 4820 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 4821 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 4822 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 4823 ins_cost(150); 4824 4825 size(4); 4826 format %{ "MOV$cmp $dst,$src\t! ptr" %} 4827 ins_encode %{ 4828 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 4829 %} 4830 ins_pipe(ialu_reg); 4831%} 4832 4833instruct cmovPIu_reg(cmpOpU cmp, flagsRegU icc, iRegP dst, iRegP src) %{ 4834 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src))); 4835 ins_cost(150); 4836 4837 size(4); 4838 format %{ "MOV$cmp $dst,$src\t! ptr" %} 4839 ins_encode %{ 4840 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 4841 %} 4842 ins_pipe(ialu_reg); 4843%} 4844 4845instruct cmovPI_imm(cmpOp cmp, flagsReg icc, iRegP dst, immP0 src) %{ 4846 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src))); 4847 ins_cost(140); 4848 4849 size(4); 4850 format %{ "MOV$cmp $dst,$src\t! ptr" %} 4851 ins_encode %{ 4852 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 4853 %} 4854 ins_pipe(ialu_imm); 4855%} 4856 4857instruct cmovPI_imm_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegP dst, immP0 src) %{ 4858 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src))); 4859 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 4860 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 4861 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 4862 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 4863 ins_cost(140); 4864 4865 size(4); 4866 format %{ "MOV$cmp $dst,$src\t! ptr" %} 4867 ins_encode %{ 4868 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 4869 %} 4870 ins_pipe(ialu_imm); 4871%} 4872 4873instruct cmovPIu_imm(cmpOpU cmp, flagsRegU icc, iRegP dst, immP0 src) %{ 4874 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src))); 4875 ins_cost(140); 4876 4877 size(4); 4878 format %{ "MOV$cmp $dst,$src\t! ptr" %} 4879 ins_encode %{ 4880 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 4881 %} 4882 ins_pipe(ialu_imm); 4883%} 4884 4885 4886// Conditional move 4887instruct cmovFP_reg(cmpOpP cmp, flagsRegP pcc, regF dst, regF src) %{ 4888 match(Set dst (CMoveF (Binary cmp pcc) (Binary dst src))); 4889 ins_cost(150); 4890 size(4); 4891 format %{ "FCPYS$cmp $dst,$src" %} 4892 ins_encode %{ 4893 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 4894 %} 4895 ins_pipe(int_conditional_float_move); 4896%} 4897 4898instruct cmovFI_reg(cmpOp cmp, flagsReg icc, regF dst, regF src) %{ 4899 match(Set dst (CMoveF (Binary cmp icc) (Binary dst src))); 4900 ins_cost(150); 4901 4902 size(4); 4903 format %{ "FCPYS$cmp $dst,$src" %} 4904 ins_encode %{ 4905 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 4906 %} 4907 ins_pipe(int_conditional_float_move); 4908%} 4909 4910instruct cmovFI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, regF dst, regF src) %{ 4911 match(Set dst (CMoveF (Binary cmp icc) (Binary dst src))); 4912 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 4913 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 4914 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 4915 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 4916 ins_cost(150); 4917 4918 size(4); 4919 format %{ "FCPYS$cmp $dst,$src" %} 4920 ins_encode %{ 4921 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 4922 %} 4923 ins_pipe(int_conditional_float_move); 4924%} 4925 4926instruct cmovFIu_reg(cmpOpU cmp, flagsRegU icc, regF dst, regF src) %{ 4927 match(Set dst (CMoveF (Binary cmp icc) (Binary dst src))); 4928 ins_cost(150); 4929 4930 size(4); 4931 format %{ "FCPYS$cmp $dst,$src" %} 4932 ins_encode %{ 4933 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 4934 %} 4935 ins_pipe(int_conditional_float_move); 4936%} 4937 4938// Conditional move 4939instruct cmovDP_reg(cmpOpP cmp, flagsRegP pcc, regD dst, regD src) %{ 4940 match(Set dst (CMoveD (Binary cmp pcc) (Binary dst src))); 4941 ins_cost(150); 4942 size(4); 4943 format %{ "FCPYD$cmp $dst,$src" %} 4944 ins_encode %{ 4945 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 4946 %} 4947 ins_pipe(int_conditional_double_move); 4948%} 4949 4950instruct cmovDI_reg(cmpOp cmp, flagsReg icc, regD dst, regD src) %{ 4951 match(Set dst (CMoveD (Binary cmp icc) (Binary dst src))); 4952 ins_cost(150); 4953 4954 size(4); 4955 format %{ "FCPYD$cmp $dst,$src" %} 4956 ins_encode %{ 4957 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 4958 %} 4959 ins_pipe(int_conditional_double_move); 4960%} 4961 4962instruct cmovDI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, regD dst, regD src) %{ 4963 match(Set dst (CMoveD (Binary cmp icc) (Binary dst src))); 4964 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); 4965 ins_cost(150); 4966 4967 size(4); 4968 format %{ "FCPYD$cmp $dst,$src" %} 4969 ins_encode %{ 4970 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 4971 %} 4972 ins_pipe(int_conditional_double_move); 4973%} 4974 4975instruct cmovDIu_reg(cmpOpU cmp, flagsRegU icc, regD dst, regD src) %{ 4976 match(Set dst (CMoveD (Binary cmp icc) (Binary dst src))); 4977 ins_cost(150); 4978 4979 size(4); 4980 format %{ "FCPYD$cmp $dst,$src" %} 4981 ins_encode %{ 4982 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 4983 %} 4984 ins_pipe(int_conditional_double_move); 4985%} 4986 4987// Conditional move 4988instruct cmovLP_reg(cmpOpP cmp, flagsRegP pcc, iRegL dst, iRegL src) %{ 4989 match(Set dst (CMoveL (Binary cmp pcc) (Binary dst src))); 4990 ins_cost(150); 4991 4992 size(8); 4993 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t" 4994 "MOV$cmp $dst.hi,$src.hi" %} 4995 ins_encode %{ 4996 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 4997 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode)); 4998 %} 4999 ins_pipe(ialu_reg); 5000%} 5001 5002// TODO: try immLRot2 instead, (0, $con$$constant) becomes 5003// (hi($con$$constant), lo($con$$constant)) becomes 5004instruct cmovLP_immRot(cmpOpP cmp, flagsRegP pcc, iRegL dst, immLlowRot src) %{ 5005 match(Set dst (CMoveL (Binary cmp pcc) (Binary dst src))); 5006 ins_cost(140); 5007 5008 size(8); 5009 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t" 5010 "MOV$cmp $dst.hi,0" %} 5011 ins_encode %{ 5012 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 5013 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 5014 %} 5015 ins_pipe(ialu_imm); 5016%} 5017 5018instruct cmovLP_imm16(cmpOpP cmp, flagsRegP pcc, iRegL dst, immL16 src) %{ 5019 match(Set dst (CMoveL (Binary cmp pcc) (Binary dst src))); 5020 ins_cost(140); 5021 5022 size(8); 5023 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t" 5024 "MOV$cmp $dst.hi,0" %} 5025 ins_encode %{ 5026 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 5027 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 5028 %} 5029 ins_pipe(ialu_imm); 5030%} 5031 5032instruct cmovLI_reg(cmpOp cmp, flagsReg icc, iRegL dst, iRegL src) %{ 5033 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src))); 5034 ins_cost(150); 5035 5036 size(8); 5037 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t" 5038 "MOV$cmp $dst.hi,$src.hi" %} 5039 ins_encode %{ 5040 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 5041 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode)); 5042 %} 5043 ins_pipe(ialu_reg); 5044%} 5045 5046instruct cmovLI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegL dst, iRegL src) %{ 5047 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src))); 5048 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 5049 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 5050 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 5051 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 5052 ins_cost(150); 5053 5054 size(8); 5055 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t" 5056 "MOV$cmp $dst.hi,$src.hi" %} 5057 ins_encode %{ 5058 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 5059 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode)); 5060 %} 5061 ins_pipe(ialu_reg); 5062%} 5063 5064// TODO: try immLRot2 instead, (0, $con$$constant) becomes 5065// (hi($con$$constant), lo($con$$constant)) becomes 5066instruct cmovLI_immRot(cmpOp cmp, flagsReg icc, iRegL dst, immLlowRot src) %{ 5067 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src))); 5068 ins_cost(140); 5069 5070 size(8); 5071 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t" 5072 "MOV$cmp $dst.hi,0" %} 5073 ins_encode %{ 5074 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 5075 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 5076 %} 5077 ins_pipe(ialu_imm); 5078%} 5079 5080// TODO: try immLRot2 instead, (0, $con$$constant) becomes 5081// (hi($con$$constant), lo($con$$constant)) becomes 5082instruct cmovLI_immRot_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegL dst, immLlowRot src) %{ 5083 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src))); 5084 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 5085 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 5086 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 5087 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 5088 ins_cost(140); 5089 5090 size(8); 5091 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t" 5092 "MOV$cmp $dst.hi,0" %} 5093 ins_encode %{ 5094 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 5095 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 5096 %} 5097 ins_pipe(ialu_imm); 5098%} 5099 5100instruct cmovLI_imm16(cmpOp cmp, flagsReg icc, iRegL dst, immL16 src) %{ 5101 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src))); 5102 ins_cost(140); 5103 5104 size(8); 5105 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t" 5106 "MOV$cmp $dst.hi,0" %} 5107 ins_encode %{ 5108 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 5109 __ movw($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 5110 %} 5111 ins_pipe(ialu_imm); 5112%} 5113 5114instruct cmovLI_imm16_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegL dst, immL16 src) %{ 5115 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src))); 5116 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 5117 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 5118 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 5119 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 5120 ins_cost(140); 5121 5122 size(8); 5123 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t" 5124 "MOV$cmp $dst.hi,0" %} 5125 ins_encode %{ 5126 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 5127 __ movw($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 5128 %} 5129 ins_pipe(ialu_imm); 5130%} 5131 5132instruct cmovLIu_reg(cmpOpU cmp, flagsRegU icc, iRegL dst, iRegL src) %{ 5133 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src))); 5134 ins_cost(150); 5135 5136 size(8); 5137 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t" 5138 "MOV$cmp $dst.hi,$src.hi" %} 5139 ins_encode %{ 5140 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 5141 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode)); 5142 %} 5143 ins_pipe(ialu_reg); 5144%} 5145 5146 5147//----------OS and Locking Instructions---------------------------------------- 5148 5149// This name is KNOWN by the ADLC and cannot be changed. 5150// The ADLC forces a 'TypeRawPtr::BOTTOM' output type 5151// for this guy. 5152instruct tlsLoadP(RthreadRegP dst) %{ 5153 match(Set dst (ThreadLocal)); 5154 5155 size(0); 5156 ins_cost(0); 5157 format %{ "! TLS is in $dst" %} 5158 ins_encode( /*empty encoding*/ ); 5159 ins_pipe(ialu_none); 5160%} 5161 5162instruct checkCastPP( iRegP dst ) %{ 5163 match(Set dst (CheckCastPP dst)); 5164 5165 size(0); 5166 format %{ "! checkcastPP of $dst" %} 5167 ins_encode( /*empty encoding*/ ); 5168 ins_pipe(empty); 5169%} 5170 5171 5172instruct castPP( iRegP dst ) %{ 5173 match(Set dst (CastPP dst)); 5174 format %{ "! castPP of $dst" %} 5175 ins_encode( /*empty encoding*/ ); 5176 ins_pipe(empty); 5177%} 5178 5179instruct castII( iRegI dst ) %{ 5180 match(Set dst (CastII dst)); 5181 format %{ "! castII of $dst" %} 5182 ins_encode( /*empty encoding*/ ); 5183 ins_cost(0); 5184 ins_pipe(empty); 5185%} 5186 5187instruct castLL( iRegL dst ) %{ 5188 match(Set dst (CastLL dst)); 5189 format %{ "! castLL of $dst" %} 5190 ins_encode( /*empty encoding*/ ); 5191 ins_cost(0); 5192 ins_pipe(empty); 5193%} 5194 5195instruct castFF( regF dst ) %{ 5196 match(Set dst (CastFF dst)); 5197 format %{ "! castFF of $dst" %} 5198 ins_encode( /*empty encoding*/ ); 5199 ins_cost(0); 5200 ins_pipe(empty); 5201%} 5202 5203instruct castDD( regD dst ) %{ 5204 match(Set dst (CastDD dst)); 5205 format %{ "! castDD of $dst" %} 5206 ins_encode( /*empty encoding*/ ); 5207 ins_cost(0); 5208 ins_pipe(empty); 5209%} 5210 5211instruct castVVD( vecD dst ) %{ 5212 match(Set dst (CastVV dst)); 5213 format %{ "! castVV of $dst" %} 5214 ins_encode( /*empty encoding*/ ); 5215 ins_cost(0); 5216 ins_pipe(empty); 5217%} 5218 5219instruct castVVX( vecX dst ) %{ 5220 match(Set dst (CastVV dst)); 5221 format %{ "! castVV of $dst" %} 5222 ins_encode( /*empty encoding*/ ); 5223 ins_cost(0); 5224 ins_pipe(empty); 5225%} 5226 5227 5228//----------Arithmetic Instructions-------------------------------------------- 5229// Addition Instructions 5230// Register Addition 5231instruct addI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 5232 match(Set dst (AddI src1 src2)); 5233 5234 size(4); 5235 format %{ "add_32 $dst,$src1,$src2\t! int" %} 5236 ins_encode %{ 5237 __ add_32($dst$$Register, $src1$$Register, $src2$$Register); 5238 %} 5239 ins_pipe(ialu_reg_reg); 5240%} 5241 5242instruct addshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 5243 match(Set dst (AddI (LShiftI src1 src2) src3)); 5244 5245 size(4); 5246 format %{ "add_32 $dst,$src3,$src1<<$src2\t! int" %} 5247 ins_encode %{ 5248 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register)); 5249 %} 5250 ins_pipe(ialu_reg_reg); 5251%} 5252 5253 5254instruct addshlI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{ 5255 match(Set dst (AddI (LShiftI src1 src2) src3)); 5256 5257 size(4); 5258 format %{ "add_32 $dst,$src3,$src1<<$src2\t! int" %} 5259 ins_encode %{ 5260 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$constant)); 5261 %} 5262 ins_pipe(ialu_reg_reg); 5263%} 5264 5265instruct addsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 5266 match(Set dst (AddI (RShiftI src1 src2) src3)); 5267 5268 size(4); 5269 format %{ "add_32 $dst,$src3,$src1>>$src2\t! int" %} 5270 ins_encode %{ 5271 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$Register)); 5272 %} 5273 ins_pipe(ialu_reg_reg); 5274%} 5275 5276instruct addsarI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{ 5277 match(Set dst (AddI (RShiftI src1 src2) src3)); 5278 5279 size(4); 5280 format %{ "add_32 $dst,$src3,$src1>>$src2\t! int" %} 5281 ins_encode %{ 5282 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$constant)); 5283 %} 5284 ins_pipe(ialu_reg_reg); 5285%} 5286 5287instruct addshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 5288 match(Set dst (AddI (URShiftI src1 src2) src3)); 5289 5290 size(4); 5291 format %{ "add_32 $dst,$src3,$src1>>>$src2\t! int" %} 5292 ins_encode %{ 5293 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register)); 5294 %} 5295 ins_pipe(ialu_reg_reg); 5296%} 5297 5298instruct addshrI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{ 5299 match(Set dst (AddI (URShiftI src1 src2) src3)); 5300 5301 size(4); 5302 format %{ "add_32 $dst,$src3,$src1>>>$src2\t! int" %} 5303 ins_encode %{ 5304 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant)); 5305 %} 5306 ins_pipe(ialu_reg_reg); 5307%} 5308 5309// Immediate Addition 5310instruct addI_reg_aimmI(iRegI dst, iRegI src1, aimmI src2) %{ 5311 match(Set dst (AddI src1 src2)); 5312 5313 size(4); 5314 format %{ "add_32 $dst,$src1,$src2\t! int" %} 5315 ins_encode %{ 5316 __ add_32($dst$$Register, $src1$$Register, $src2$$constant); 5317 %} 5318 ins_pipe(ialu_reg_imm); 5319%} 5320 5321// Pointer Register Addition 5322instruct addP_reg_reg(iRegP dst, iRegP src1, iRegX src2) %{ 5323 match(Set dst (AddP src1 src2)); 5324 5325 size(4); 5326 format %{ "ADD $dst,$src1,$src2\t! ptr" %} 5327 ins_encode %{ 5328 __ add($dst$$Register, $src1$$Register, $src2$$Register); 5329 %} 5330 ins_pipe(ialu_reg_reg); 5331%} 5332 5333 5334// shifted iRegX operand 5335operand shiftedX(iRegX src2, shimmX src3) %{ 5336//constraint(ALLOC_IN_RC(sp_ptr_reg)); 5337 match(LShiftX src2 src3); 5338 5339 op_cost(1); 5340 format %{ "$src2 << $src3" %} 5341 interface(MEMORY_INTER) %{ 5342 base($src2); 5343 index(0xff); 5344 scale($src3); 5345 disp(0x0); 5346 %} 5347%} 5348 5349instruct addshlP_reg_reg_imm(iRegP dst, iRegP src1, shiftedX src2) %{ 5350 match(Set dst (AddP src1 src2)); 5351 5352 ins_cost(DEFAULT_COST * 3/2); 5353 size(4); 5354 format %{ "ADD $dst,$src1,$src2\t! ptr" %} 5355 ins_encode %{ 5356 Register base = reg_to_register_object($src2$$base); 5357 __ add($dst$$Register, $src1$$Register, AsmOperand(base, lsl, $src2$$scale)); 5358 %} 5359 ins_pipe(ialu_reg_reg); 5360%} 5361 5362// Pointer Immediate Addition 5363instruct addP_reg_aimmX(iRegP dst, iRegP src1, aimmX src2) %{ 5364 match(Set dst (AddP src1 src2)); 5365 5366 size(4); 5367 format %{ "ADD $dst,$src1,$src2\t! ptr" %} 5368 ins_encode %{ 5369 __ add($dst$$Register, $src1$$Register, $src2$$constant); 5370 %} 5371 ins_pipe(ialu_reg_imm); 5372%} 5373 5374// Long Addition 5375instruct addL_reg_reg(iRegL dst, iRegL src1, iRegL src2, flagsReg ccr) %{ 5376 match(Set dst (AddL src1 src2)); 5377 effect(KILL ccr); 5378 size(8); 5379 format %{ "ADDS $dst.lo,$src1.lo,$src2.lo\t! long\n\t" 5380 "ADC $dst.hi,$src1.hi,$src2.hi" %} 5381 ins_encode %{ 5382 __ adds($dst$$Register, $src1$$Register, $src2$$Register); 5383 __ adc($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor()); 5384 %} 5385 ins_pipe(ialu_reg_reg); 5386%} 5387 5388// TODO 5389 5390// TODO: try immLRot2 instead, (0, $con$$constant) becomes 5391// (hi($con$$constant), lo($con$$constant)) becomes 5392instruct addL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con, flagsReg ccr) %{ 5393 match(Set dst (AddL src1 con)); 5394 effect(KILL ccr); 5395 size(8); 5396 format %{ "ADDS $dst.lo,$src1.lo,$con\t! long\n\t" 5397 "ADC $dst.hi,$src1.hi,0" %} 5398 ins_encode %{ 5399 __ adds($dst$$Register, $src1$$Register, $con$$constant); 5400 __ adc($dst$$Register->successor(), $src1$$Register->successor(), 0); 5401 %} 5402 ins_pipe(ialu_reg_imm); 5403%} 5404 5405//----------Conditional_store-------------------------------------------------- 5406// Conditional-store of the updated heap-top. 5407// Used during allocation of the shared heap. 5408// Sets flags (EQ) on success. 5409 5410// LoadP-locked. 5411instruct loadPLocked(iRegP dst, memoryex mem) %{ 5412 match(Set dst (LoadPLocked mem)); 5413 size(4); 5414 format %{ "LDREX $dst,$mem" %} 5415 ins_encode %{ 5416 __ ldrex($dst$$Register,$mem$$Address); 5417 %} 5418 ins_pipe(iload_mem); 5419%} 5420 5421instruct storePConditional( memoryex heap_top_ptr, iRegP oldval, iRegP newval, iRegI tmp, flagsRegP pcc ) %{ 5422 predicate(_kids[1]->_kids[0]->_leaf->Opcode() == Op_LoadPLocked); // only works in conjunction with a LoadPLocked node 5423 match(Set pcc (StorePConditional heap_top_ptr (Binary oldval newval))); 5424 effect( TEMP tmp ); 5425 size(8); 5426 format %{ "STREX $tmp,$newval,$heap_top_ptr\n\t" 5427 "CMP $tmp, 0" %} 5428 ins_encode %{ 5429 __ strex($tmp$$Register, $newval$$Register, $heap_top_ptr$$Address); 5430 __ cmp($tmp$$Register, 0); 5431 %} 5432 ins_pipe( long_memory_op ); 5433%} 5434 5435// Conditional-store of an intx value. 5436instruct storeXConditional( memoryex mem, iRegX oldval, iRegX newval, iRegX tmp, flagsReg icc ) %{ 5437 match(Set icc (StoreIConditional mem (Binary oldval newval))); 5438 effect( TEMP tmp ); 5439 size(28); 5440 format %{ "loop: \n\t" 5441 "LDREX $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem], DOESN'T set $newval=[$mem] in any case\n\t" 5442 "XORS $tmp,$tmp, $oldval\n\t" 5443 "STREX.eq $tmp, $newval, $mem\n\t" 5444 "CMP.eq $tmp, 1 \n\t" 5445 "B.eq loop \n\t" 5446 "TEQ $tmp, 0\n\t" 5447 "membar LoadStore|LoadLoad" %} 5448 ins_encode %{ 5449 Label loop; 5450 __ bind(loop); 5451 __ ldrex($tmp$$Register, $mem$$Address); 5452 __ eors($tmp$$Register, $tmp$$Register, $oldval$$Register); 5453 __ strex($tmp$$Register, $newval$$Register, $mem$$Address, eq); 5454 __ cmp($tmp$$Register, 1, eq); 5455 __ b(loop, eq); 5456 __ teq($tmp$$Register, 0); 5457 // used by biased locking only. Requires a membar. 5458 __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::LoadStore | MacroAssembler::LoadLoad), noreg); 5459 %} 5460 ins_pipe( long_memory_op ); 5461%} 5462 5463// No flag versions for CompareAndSwap{P,I,L} because matcher can't match them 5464 5465instruct compareAndSwapL_bool(memoryex mem, iRegL oldval, iRegLd newval, iRegI res, iRegLd tmp, flagsReg ccr ) %{ 5466 match(Set res (CompareAndSwapL mem (Binary oldval newval))); 5467 effect( KILL ccr, TEMP tmp); 5468 size(32); 5469 format %{ "loop: \n\t" 5470 "LDREXD $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t" 5471 "CMP $tmp.lo, $oldval.lo\n\t" 5472 "CMP.eq $tmp.hi, $oldval.hi\n\t" 5473 "STREXD.eq $tmp, $newval, $mem\n\t" 5474 "MOV.ne $tmp, 0 \n\t" 5475 "XORS.eq $tmp,$tmp, 1 \n\t" 5476 "B.eq loop \n\t" 5477 "MOV $res, $tmp" %} 5478 ins_encode %{ 5479 Label loop; 5480 __ bind(loop); 5481 __ ldrexd($tmp$$Register, $mem$$Address); 5482 __ cmp($tmp$$Register, $oldval$$Register); 5483 __ cmp($tmp$$Register->successor(), $oldval$$Register->successor(), eq); 5484 __ strexd($tmp$$Register, $newval$$Register, $mem$$Address, eq); 5485 __ mov($tmp$$Register, 0, ne); 5486 __ eors($tmp$$Register, $tmp$$Register, 1, eq); 5487 __ b(loop, eq); 5488 __ mov($res$$Register, $tmp$$Register); 5489 %} 5490 ins_pipe( long_memory_op ); 5491%} 5492 5493 5494instruct compareAndSwapI_bool(memoryex mem, iRegI oldval, iRegI newval, iRegI res, iRegI tmp, flagsReg ccr ) %{ 5495 match(Set res (CompareAndSwapI mem (Binary oldval newval))); 5496 effect( KILL ccr, TEMP tmp); 5497 size(28); 5498 format %{ "loop: \n\t" 5499 "LDREX $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t" 5500 "CMP $tmp, $oldval\n\t" 5501 "STREX.eq $tmp, $newval, $mem\n\t" 5502 "MOV.ne $tmp, 0 \n\t" 5503 "XORS.eq $tmp,$tmp, 1 \n\t" 5504 "B.eq loop \n\t" 5505 "MOV $res, $tmp" %} 5506 5507 ins_encode %{ 5508 Label loop; 5509 __ bind(loop); 5510 __ ldrex($tmp$$Register,$mem$$Address); 5511 __ cmp($tmp$$Register, $oldval$$Register); 5512 __ strex($tmp$$Register, $newval$$Register, $mem$$Address, eq); 5513 __ mov($tmp$$Register, 0, ne); 5514 __ eors($tmp$$Register, $tmp$$Register, 1, eq); 5515 __ b(loop, eq); 5516 __ mov($res$$Register, $tmp$$Register); 5517 %} 5518 ins_pipe( long_memory_op ); 5519%} 5520 5521instruct compareAndSwapP_bool(memoryex mem, iRegP oldval, iRegP newval, iRegI res, iRegI tmp, flagsReg ccr ) %{ 5522 match(Set res (CompareAndSwapP mem (Binary oldval newval))); 5523 effect( KILL ccr, TEMP tmp); 5524 size(28); 5525 format %{ "loop: \n\t" 5526 "LDREX $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t" 5527 "CMP $tmp, $oldval\n\t" 5528 "STREX.eq $tmp, $newval, $mem\n\t" 5529 "MOV.ne $tmp, 0 \n\t" 5530 "EORS.eq $tmp,$tmp, 1 \n\t" 5531 "B.eq loop \n\t" 5532 "MOV $res, $tmp" %} 5533 5534 ins_encode %{ 5535 Label loop; 5536 __ bind(loop); 5537 __ ldrex($tmp$$Register,$mem$$Address); 5538 __ cmp($tmp$$Register, $oldval$$Register); 5539 __ strex($tmp$$Register, $newval$$Register, $mem$$Address, eq); 5540 __ mov($tmp$$Register, 0, ne); 5541 __ eors($tmp$$Register, $tmp$$Register, 1, eq); 5542 __ b(loop, eq); 5543 __ mov($res$$Register, $tmp$$Register); 5544 %} 5545 ins_pipe( long_memory_op ); 5546%} 5547 5548instruct xaddI_aimmI_no_res(memoryex mem, aimmI add, Universe dummy, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{ 5549 predicate(n->as_LoadStore()->result_not_used()); 5550 match(Set dummy (GetAndAddI mem add)); 5551 effect(KILL ccr, TEMP tmp1, TEMP tmp2); 5552 size(20); 5553 format %{ "loop: \n\t" 5554 "LDREX $tmp1, $mem\n\t" 5555 "ADD $tmp1, $tmp1, $add\n\t" 5556 "STREX $tmp2, $tmp1, $mem\n\t" 5557 "CMP $tmp2, 0 \n\t" 5558 "B.ne loop \n\t" %} 5559 5560 ins_encode %{ 5561 Label loop; 5562 __ bind(loop); 5563 __ ldrex($tmp1$$Register,$mem$$Address); 5564 __ add($tmp1$$Register, $tmp1$$Register, $add$$constant); 5565 __ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address); 5566 __ cmp($tmp2$$Register, 0); 5567 __ b(loop, ne); 5568 %} 5569 ins_pipe( long_memory_op ); 5570%} 5571 5572instruct xaddI_reg_no_res(memoryex mem, iRegI add, Universe dummy, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{ 5573 predicate(n->as_LoadStore()->result_not_used()); 5574 match(Set dummy (GetAndAddI mem add)); 5575 effect(KILL ccr, TEMP tmp1, TEMP tmp2); 5576 size(20); 5577 format %{ "loop: \n\t" 5578 "LDREX $tmp1, $mem\n\t" 5579 "ADD $tmp1, $tmp1, $add\n\t" 5580 "STREX $tmp2, $tmp1, $mem\n\t" 5581 "CMP $tmp2, 0 \n\t" 5582 "B.ne loop \n\t" %} 5583 5584 ins_encode %{ 5585 Label loop; 5586 __ bind(loop); 5587 __ ldrex($tmp1$$Register,$mem$$Address); 5588 __ add($tmp1$$Register, $tmp1$$Register, $add$$Register); 5589 __ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address); 5590 __ cmp($tmp2$$Register, 0); 5591 __ b(loop, ne); 5592 %} 5593 ins_pipe( long_memory_op ); 5594%} 5595 5596instruct xaddI_aimmI(memoryex mem, aimmI add, iRegI res, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{ 5597 match(Set res (GetAndAddI mem add)); 5598 effect(KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res); 5599 size(20); 5600 format %{ "loop: \n\t" 5601 "LDREX $res, $mem\n\t" 5602 "ADD $tmp1, $res, $add\n\t" 5603 "STREX $tmp2, $tmp1, $mem\n\t" 5604 "CMP $tmp2, 0 \n\t" 5605 "B.ne loop \n\t" %} 5606 5607 ins_encode %{ 5608 Label loop; 5609 __ bind(loop); 5610 __ ldrex($res$$Register,$mem$$Address); 5611 __ add($tmp1$$Register, $res$$Register, $add$$constant); 5612 __ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address); 5613 __ cmp($tmp2$$Register, 0); 5614 __ b(loop, ne); 5615 %} 5616 ins_pipe( long_memory_op ); 5617%} 5618 5619instruct xaddI_reg(memoryex mem, iRegI add, iRegI res, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{ 5620 match(Set res (GetAndAddI mem add)); 5621 effect(KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res); 5622 size(20); 5623 format %{ "loop: \n\t" 5624 "LDREX $res, $mem\n\t" 5625 "ADD $tmp1, $res, $add\n\t" 5626 "STREX $tmp2, $tmp1, $mem\n\t" 5627 "CMP $tmp2, 0 \n\t" 5628 "B.ne loop \n\t" %} 5629 5630 ins_encode %{ 5631 Label loop; 5632 __ bind(loop); 5633 __ ldrex($res$$Register,$mem$$Address); 5634 __ add($tmp1$$Register, $res$$Register, $add$$Register); 5635 __ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address); 5636 __ cmp($tmp2$$Register, 0); 5637 __ b(loop, ne); 5638 %} 5639 ins_pipe( long_memory_op ); 5640%} 5641 5642instruct xaddL_reg_no_res(memoryex mem, iRegL add, Universe dummy, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{ 5643 predicate(n->as_LoadStore()->result_not_used()); 5644 match(Set dummy (GetAndAddL mem add)); 5645 effect( KILL ccr, TEMP tmp1, TEMP tmp2); 5646 size(24); 5647 format %{ "loop: \n\t" 5648 "LDREXD $tmp1, $mem\n\t" 5649 "ADDS $tmp1.lo, $tmp1.lo, $add.lo\n\t" 5650 "ADC $tmp1.hi, $tmp1.hi, $add.hi\n\t" 5651 "STREXD $tmp2, $tmp1, $mem\n\t" 5652 "CMP $tmp2, 0 \n\t" 5653 "B.ne loop \n\t" %} 5654 5655 ins_encode %{ 5656 Label loop; 5657 __ bind(loop); 5658 __ ldrexd($tmp1$$Register, $mem$$Address); 5659 __ adds($tmp1$$Register, $tmp1$$Register, $add$$Register); 5660 __ adc($tmp1$$Register->successor(), $tmp1$$Register->successor(), $add$$Register->successor()); 5661 __ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address); 5662 __ cmp($tmp2$$Register, 0); 5663 __ b(loop, ne); 5664 %} 5665 ins_pipe( long_memory_op ); 5666%} 5667 5668// TODO: try immLRot2 instead, (0, $con$$constant) becomes 5669// (hi($con$$constant), lo($con$$constant)) becomes 5670instruct xaddL_immRot_no_res(memoryex mem, immLlowRot add, Universe dummy, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{ 5671 predicate(n->as_LoadStore()->result_not_used()); 5672 match(Set dummy (GetAndAddL mem add)); 5673 effect( KILL ccr, TEMP tmp1, TEMP tmp2); 5674 size(24); 5675 format %{ "loop: \n\t" 5676 "LDREXD $tmp1, $mem\n\t" 5677 "ADDS $tmp1.lo, $tmp1.lo, $add\n\t" 5678 "ADC $tmp1.hi, $tmp1.hi, 0\n\t" 5679 "STREXD $tmp2, $tmp1, $mem\n\t" 5680 "CMP $tmp2, 0 \n\t" 5681 "B.ne loop \n\t" %} 5682 5683 ins_encode %{ 5684 Label loop; 5685 __ bind(loop); 5686 __ ldrexd($tmp1$$Register, $mem$$Address); 5687 __ adds($tmp1$$Register, $tmp1$$Register, $add$$constant); 5688 __ adc($tmp1$$Register->successor(), $tmp1$$Register->successor(), 0); 5689 __ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address); 5690 __ cmp($tmp2$$Register, 0); 5691 __ b(loop, ne); 5692 %} 5693 ins_pipe( long_memory_op ); 5694%} 5695 5696instruct xaddL_reg(memoryex mem, iRegL add, iRegLd res, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{ 5697 match(Set res (GetAndAddL mem add)); 5698 effect( KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res); 5699 size(24); 5700 format %{ "loop: \n\t" 5701 "LDREXD $res, $mem\n\t" 5702 "ADDS $tmp1.lo, $res.lo, $add.lo\n\t" 5703 "ADC $tmp1.hi, $res.hi, $add.hi\n\t" 5704 "STREXD $tmp2, $tmp1, $mem\n\t" 5705 "CMP $tmp2, 0 \n\t" 5706 "B.ne loop \n\t" %} 5707 5708 ins_encode %{ 5709 Label loop; 5710 __ bind(loop); 5711 __ ldrexd($res$$Register, $mem$$Address); 5712 __ adds($tmp1$$Register, $res$$Register, $add$$Register); 5713 __ adc($tmp1$$Register->successor(), $res$$Register->successor(), $add$$Register->successor()); 5714 __ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address); 5715 __ cmp($tmp2$$Register, 0); 5716 __ b(loop, ne); 5717 %} 5718 ins_pipe( long_memory_op ); 5719%} 5720 5721// TODO: try immLRot2 instead, (0, $con$$constant) becomes 5722// (hi($con$$constant), lo($con$$constant)) becomes 5723instruct xaddL_immRot(memoryex mem, immLlowRot add, iRegLd res, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{ 5724 match(Set res (GetAndAddL mem add)); 5725 effect( KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res); 5726 size(24); 5727 format %{ "loop: \n\t" 5728 "LDREXD $res, $mem\n\t" 5729 "ADDS $tmp1.lo, $res.lo, $add\n\t" 5730 "ADC $tmp1.hi, $res.hi, 0\n\t" 5731 "STREXD $tmp2, $tmp1, $mem\n\t" 5732 "CMP $tmp2, 0 \n\t" 5733 "B.ne loop \n\t" %} 5734 5735 ins_encode %{ 5736 Label loop; 5737 __ bind(loop); 5738 __ ldrexd($res$$Register, $mem$$Address); 5739 __ adds($tmp1$$Register, $res$$Register, $add$$constant); 5740 __ adc($tmp1$$Register->successor(), $res$$Register->successor(), 0); 5741 __ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address); 5742 __ cmp($tmp2$$Register, 0); 5743 __ b(loop, ne); 5744 %} 5745 ins_pipe( long_memory_op ); 5746%} 5747 5748instruct xchgI(memoryex mem, iRegI newval, iRegI res, iRegI tmp, flagsReg ccr) %{ 5749 match(Set res (GetAndSetI mem newval)); 5750 effect(KILL ccr, TEMP tmp, TEMP res); 5751 size(16); 5752 format %{ "loop: \n\t" 5753 "LDREX $res, $mem\n\t" 5754 "STREX $tmp, $newval, $mem\n\t" 5755 "CMP $tmp, 0 \n\t" 5756 "B.ne loop \n\t" %} 5757 5758 ins_encode %{ 5759 Label loop; 5760 __ bind(loop); 5761 __ ldrex($res$$Register,$mem$$Address); 5762 __ strex($tmp$$Register, $newval$$Register, $mem$$Address); 5763 __ cmp($tmp$$Register, 0); 5764 __ b(loop, ne); 5765 %} 5766 ins_pipe( long_memory_op ); 5767%} 5768 5769instruct xchgL(memoryex mem, iRegLd newval, iRegLd res, iRegI tmp, flagsReg ccr) %{ 5770 match(Set res (GetAndSetL mem newval)); 5771 effect( KILL ccr, TEMP tmp, TEMP res); 5772 size(16); 5773 format %{ "loop: \n\t" 5774 "LDREXD $res, $mem\n\t" 5775 "STREXD $tmp, $newval, $mem\n\t" 5776 "CMP $tmp, 0 \n\t" 5777 "B.ne loop \n\t" %} 5778 5779 ins_encode %{ 5780 Label loop; 5781 __ bind(loop); 5782 __ ldrexd($res$$Register, $mem$$Address); 5783 __ strexd($tmp$$Register, $newval$$Register, $mem$$Address); 5784 __ cmp($tmp$$Register, 0); 5785 __ b(loop, ne); 5786 %} 5787 ins_pipe( long_memory_op ); 5788%} 5789 5790instruct xchgP(memoryex mem, iRegP newval, iRegP res, iRegI tmp, flagsReg ccr) %{ 5791 match(Set res (GetAndSetP mem newval)); 5792 effect(KILL ccr, TEMP tmp, TEMP res); 5793 size(16); 5794 format %{ "loop: \n\t" 5795 "LDREX $res, $mem\n\t" 5796 "STREX $tmp, $newval, $mem\n\t" 5797 "CMP $tmp, 0 \n\t" 5798 "B.ne loop \n\t" %} 5799 5800 ins_encode %{ 5801 Label loop; 5802 __ bind(loop); 5803 __ ldrex($res$$Register,$mem$$Address); 5804 __ strex($tmp$$Register, $newval$$Register, $mem$$Address); 5805 __ cmp($tmp$$Register, 0); 5806 __ b(loop, ne); 5807 %} 5808 ins_pipe( long_memory_op ); 5809%} 5810 5811//--------------------- 5812// Subtraction Instructions 5813// Register Subtraction 5814instruct subI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 5815 match(Set dst (SubI src1 src2)); 5816 5817 size(4); 5818 format %{ "sub_32 $dst,$src1,$src2\t! int" %} 5819 ins_encode %{ 5820 __ sub_32($dst$$Register, $src1$$Register, $src2$$Register); 5821 %} 5822 ins_pipe(ialu_reg_reg); 5823%} 5824 5825instruct subshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 5826 match(Set dst (SubI src1 (LShiftI src2 src3))); 5827 5828 size(4); 5829 format %{ "SUB $dst,$src1,$src2<<$src3" %} 5830 ins_encode %{ 5831 __ sub($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register)); 5832 %} 5833 ins_pipe(ialu_reg_reg); 5834%} 5835 5836instruct subshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 5837 match(Set dst (SubI src1 (LShiftI src2 src3))); 5838 5839 size(4); 5840 format %{ "sub_32 $dst,$src1,$src2<<$src3\t! int" %} 5841 ins_encode %{ 5842 __ sub_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant)); 5843 %} 5844 ins_pipe(ialu_reg_reg); 5845%} 5846 5847instruct subsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 5848 match(Set dst (SubI src1 (RShiftI src2 src3))); 5849 5850 size(4); 5851 format %{ "SUB $dst,$src1,$src2>>$src3" %} 5852 ins_encode %{ 5853 __ sub($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register)); 5854 %} 5855 ins_pipe(ialu_reg_reg); 5856%} 5857 5858instruct subsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 5859 match(Set dst (SubI src1 (RShiftI src2 src3))); 5860 5861 size(4); 5862 format %{ "sub_32 $dst,$src1,$src2>>$src3\t! int" %} 5863 ins_encode %{ 5864 __ sub_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant)); 5865 %} 5866 ins_pipe(ialu_reg_reg); 5867%} 5868 5869instruct subshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 5870 match(Set dst (SubI src1 (URShiftI src2 src3))); 5871 5872 size(4); 5873 format %{ "SUB $dst,$src1,$src2>>>$src3" %} 5874 ins_encode %{ 5875 __ sub($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register)); 5876 %} 5877 ins_pipe(ialu_reg_reg); 5878%} 5879 5880instruct subshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 5881 match(Set dst (SubI src1 (URShiftI src2 src3))); 5882 5883 size(4); 5884 format %{ "sub_32 $dst,$src1,$src2>>>$src3\t! int" %} 5885 ins_encode %{ 5886 __ sub_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant)); 5887 %} 5888 ins_pipe(ialu_reg_reg); 5889%} 5890 5891instruct rsbshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 5892 match(Set dst (SubI (LShiftI src1 src2) src3)); 5893 5894 size(4); 5895 format %{ "RSB $dst,$src3,$src1<<$src2" %} 5896 ins_encode %{ 5897 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register)); 5898 %} 5899 ins_pipe(ialu_reg_reg); 5900%} 5901 5902instruct rsbshlI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{ 5903 match(Set dst (SubI (LShiftI src1 src2) src3)); 5904 5905 size(4); 5906 format %{ "RSB $dst,$src3,$src1<<$src2" %} 5907 ins_encode %{ 5908 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$constant)); 5909 %} 5910 ins_pipe(ialu_reg_reg); 5911%} 5912 5913instruct rsbsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 5914 match(Set dst (SubI (RShiftI src1 src2) src3)); 5915 5916 size(4); 5917 format %{ "RSB $dst,$src3,$src1>>$src2" %} 5918 ins_encode %{ 5919 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$Register)); 5920 %} 5921 ins_pipe(ialu_reg_reg); 5922%} 5923 5924instruct rsbsarI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{ 5925 match(Set dst (SubI (RShiftI src1 src2) src3)); 5926 5927 size(4); 5928 format %{ "RSB $dst,$src3,$src1>>$src2" %} 5929 ins_encode %{ 5930 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$constant)); 5931 %} 5932 ins_pipe(ialu_reg_reg); 5933%} 5934 5935instruct rsbshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 5936 match(Set dst (SubI (URShiftI src1 src2) src3)); 5937 5938 size(4); 5939 format %{ "RSB $dst,$src3,$src1>>>$src2" %} 5940 ins_encode %{ 5941 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register)); 5942 %} 5943 ins_pipe(ialu_reg_reg); 5944%} 5945 5946instruct rsbshrI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{ 5947 match(Set dst (SubI (URShiftI src1 src2) src3)); 5948 5949 size(4); 5950 format %{ "RSB $dst,$src3,$src1>>>$src2" %} 5951 ins_encode %{ 5952 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant)); 5953 %} 5954 ins_pipe(ialu_reg_reg); 5955%} 5956 5957// Immediate Subtraction 5958instruct subI_reg_aimmI(iRegI dst, iRegI src1, aimmI src2) %{ 5959 match(Set dst (SubI src1 src2)); 5960 5961 size(4); 5962 format %{ "sub_32 $dst,$src1,$src2\t! int" %} 5963 ins_encode %{ 5964 __ sub_32($dst$$Register, $src1$$Register, $src2$$constant); 5965 %} 5966 ins_pipe(ialu_reg_imm); 5967%} 5968 5969instruct subI_reg_immRotneg(iRegI dst, iRegI src1, aimmIneg src2) %{ 5970 match(Set dst (AddI src1 src2)); 5971 5972 size(4); 5973 format %{ "sub_32 $dst,$src1,-($src2)\t! int" %} 5974 ins_encode %{ 5975 __ sub_32($dst$$Register, $src1$$Register, -$src2$$constant); 5976 %} 5977 ins_pipe(ialu_reg_imm); 5978%} 5979 5980instruct subI_immRot_reg(iRegI dst, immIRot src1, iRegI src2) %{ 5981 match(Set dst (SubI src1 src2)); 5982 5983 size(4); 5984 format %{ "RSB $dst,$src2,src1" %} 5985 ins_encode %{ 5986 __ rsb($dst$$Register, $src2$$Register, $src1$$constant); 5987 %} 5988 ins_pipe(ialu_zero_reg); 5989%} 5990 5991// Register Subtraction 5992instruct subL_reg_reg(iRegL dst, iRegL src1, iRegL src2, flagsReg icc ) %{ 5993 match(Set dst (SubL src1 src2)); 5994 effect (KILL icc); 5995 5996 size(8); 5997 format %{ "SUBS $dst.lo,$src1.lo,$src2.lo\t! long\n\t" 5998 "SBC $dst.hi,$src1.hi,$src2.hi" %} 5999 ins_encode %{ 6000 __ subs($dst$$Register, $src1$$Register, $src2$$Register); 6001 __ sbc($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor()); 6002 %} 6003 ins_pipe(ialu_reg_reg); 6004%} 6005 6006// TODO 6007 6008// Immediate Subtraction 6009// TODO: try immLRot2 instead, (0, $con$$constant) becomes 6010// (hi($con$$constant), lo($con$$constant)) becomes 6011instruct subL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con, flagsReg icc) %{ 6012 match(Set dst (SubL src1 con)); 6013 effect (KILL icc); 6014 6015 size(8); 6016 format %{ "SUB $dst.lo,$src1.lo,$con\t! long\n\t" 6017 "SBC $dst.hi,$src1.hi,0" %} 6018 ins_encode %{ 6019 __ subs($dst$$Register, $src1$$Register, $con$$constant); 6020 __ sbc($dst$$Register->successor(), $src1$$Register->successor(), 0); 6021 %} 6022 ins_pipe(ialu_reg_imm); 6023%} 6024 6025// Long negation 6026instruct negL_reg_reg(iRegL dst, immL0 zero, iRegL src2, flagsReg icc) %{ 6027 match(Set dst (SubL zero src2)); 6028 effect (KILL icc); 6029 6030 size(8); 6031 format %{ "RSBS $dst.lo,$src2.lo,0\t! long\n\t" 6032 "RSC $dst.hi,$src2.hi,0" %} 6033 ins_encode %{ 6034 __ rsbs($dst$$Register, $src2$$Register, 0); 6035 __ rsc($dst$$Register->successor(), $src2$$Register->successor(), 0); 6036 %} 6037 ins_pipe(ialu_zero_reg); 6038%} 6039 6040// Multiplication Instructions 6041// Integer Multiplication 6042// Register Multiplication 6043instruct mulI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 6044 match(Set dst (MulI src1 src2)); 6045 6046 size(4); 6047 format %{ "mul_32 $dst,$src1,$src2" %} 6048 ins_encode %{ 6049 __ mul_32($dst$$Register, $src1$$Register, $src2$$Register); 6050 %} 6051 ins_pipe(imul_reg_reg); 6052%} 6053 6054instruct mulL_lo1_hi2(iRegL dst, iRegL src1, iRegL src2) %{ 6055 effect(DEF dst, USE src1, USE src2); 6056 size(4); 6057 format %{ "MUL $dst.hi,$src1.lo,$src2.hi\t! long" %} 6058 ins_encode %{ 6059 __ mul($dst$$Register->successor(), $src1$$Register, $src2$$Register->successor()); 6060 %} 6061 ins_pipe(imul_reg_reg); 6062%} 6063 6064instruct mulL_hi1_lo2(iRegL dst, iRegL src1, iRegL src2) %{ 6065 effect(USE_DEF dst, USE src1, USE src2); 6066 size(8); 6067 format %{ "MLA $dst.hi,$src1.hi,$src2.lo,$dst.hi\t! long\n\t" 6068 "MOV $dst.lo, 0"%} 6069 ins_encode %{ 6070 __ mla($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register, $dst$$Register->successor()); 6071 __ mov($dst$$Register, 0); 6072 %} 6073 ins_pipe(imul_reg_reg); 6074%} 6075 6076instruct mulL_lo1_lo2(iRegL dst, iRegL src1, iRegL src2) %{ 6077 effect(USE_DEF dst, USE src1, USE src2); 6078 size(4); 6079 format %{ "UMLAL $dst.lo,$dst.hi,$src1,$src2\t! long" %} 6080 ins_encode %{ 6081 __ umlal($dst$$Register, $dst$$Register->successor(), $src1$$Register, $src2$$Register); 6082 %} 6083 ins_pipe(imul_reg_reg); 6084%} 6085 6086instruct mulL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{ 6087 match(Set dst (MulL src1 src2)); 6088 6089 expand %{ 6090 mulL_lo1_hi2(dst, src1, src2); 6091 mulL_hi1_lo2(dst, src1, src2); 6092 mulL_lo1_lo2(dst, src1, src2); 6093 %} 6094%} 6095 6096// Integer Division 6097// Register Division 6098instruct divI_reg_reg(R1RegI dst, R0RegI src1, R2RegI src2, LRRegP lr, flagsReg ccr) %{ 6099 match(Set dst (DivI src1 src2)); 6100 effect( KILL ccr, KILL src1, KILL src2, KILL lr); 6101 ins_cost((2+71)*DEFAULT_COST); 6102 6103 format %{ "DIV $dst,$src1,$src2 ! call to StubRoutines::Arm::idiv_irem_entry()" %} 6104 ins_encode %{ 6105 __ call(StubRoutines::Arm::idiv_irem_entry(), relocInfo::runtime_call_type); 6106 %} 6107 ins_pipe(sdiv_reg_reg); 6108%} 6109 6110// Register Long Division 6111instruct divL_reg_reg(R0R1RegL dst, R2R3RegL src1, R0R1RegL src2) %{ 6112 match(Set dst (DivL src1 src2)); 6113 effect(CALL); 6114 ins_cost(DEFAULT_COST*71); 6115 format %{ "DIVL $src1,$src2,$dst\t! long ! call to SharedRuntime::ldiv" %} 6116 ins_encode %{ 6117 address target = CAST_FROM_FN_PTR(address, SharedRuntime::ldiv); 6118 __ call(target, relocInfo::runtime_call_type); 6119 %} 6120 ins_pipe(divL_reg_reg); 6121%} 6122 6123// Integer Remainder 6124// Register Remainder 6125instruct modI_reg_reg(R0RegI dst, R0RegI src1, R2RegI src2, R1RegI temp, LRRegP lr, flagsReg ccr ) %{ 6126 match(Set dst (ModI src1 src2)); 6127 effect( KILL ccr, KILL temp, KILL src2, KILL lr); 6128 6129 format %{ "MODI $dst,$src1,$src2\t ! call to StubRoutines::Arm::idiv_irem_entry" %} 6130 ins_encode %{ 6131 __ call(StubRoutines::Arm::idiv_irem_entry(), relocInfo::runtime_call_type); 6132 %} 6133 ins_pipe(sdiv_reg_reg); 6134%} 6135 6136// Register Long Remainder 6137instruct modL_reg_reg(R0R1RegL dst, R2R3RegL src1, R0R1RegL src2) %{ 6138 match(Set dst (ModL src1 src2)); 6139 effect(CALL); 6140 ins_cost(MEMORY_REF_COST); // FIXME 6141 format %{ "modL $dst,$src1,$src2\t ! call to SharedRuntime::lrem" %} 6142 ins_encode %{ 6143 address target = CAST_FROM_FN_PTR(address, SharedRuntime::lrem); 6144 __ call(target, relocInfo::runtime_call_type); 6145 %} 6146 ins_pipe(divL_reg_reg); 6147%} 6148 6149// Integer Shift Instructions 6150 6151// Register Shift Left 6152instruct shlI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 6153 match(Set dst (LShiftI src1 src2)); 6154 6155 size(4); 6156 format %{ "LSL $dst,$src1,$src2 \n\t" %} 6157 ins_encode %{ 6158 __ mov($dst$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register)); 6159 %} 6160 ins_pipe(ialu_reg_reg); 6161%} 6162 6163// Register Shift Left Immediate 6164instruct shlI_reg_imm5(iRegI dst, iRegI src1, immU5 src2) %{ 6165 match(Set dst (LShiftI src1 src2)); 6166 6167 size(4); 6168 format %{ "LSL $dst,$src1,$src2\t! int" %} 6169 ins_encode %{ 6170 __ logical_shift_left($dst$$Register, $src1$$Register, $src2$$constant); 6171 %} 6172 ins_pipe(ialu_reg_imm); 6173%} 6174 6175instruct shlL_reg_reg_merge_hi(iRegL dst, iRegL src1, iRegI src2) %{ 6176 effect(USE_DEF dst, USE src1, USE src2); 6177 size(4); 6178 format %{"OR $dst.hi,$dst.hi,($src1.hi << $src2)" %} 6179 ins_encode %{ 6180 __ orr($dst$$Register->successor(), $dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsl, $src2$$Register)); 6181 %} 6182 ins_pipe(ialu_reg_reg); 6183%} 6184 6185instruct shlL_reg_reg_merge_lo(iRegL dst, iRegL src1, iRegI src2) %{ 6186 effect(USE_DEF dst, USE src1, USE src2); 6187 size(4); 6188 format %{ "LSL $dst.lo,$src1.lo,$src2 \n\t" %} 6189 ins_encode %{ 6190 __ mov($dst$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register)); 6191 %} 6192 ins_pipe(ialu_reg_reg); 6193%} 6194 6195instruct shlL_reg_reg_overlap(iRegL dst, iRegL src1, iRegI src2, flagsReg ccr) %{ 6196 effect(DEF dst, USE src1, USE src2, KILL ccr); 6197 size(16); 6198 format %{ "SUBS $dst.hi,$src2,32 \n\t" 6199 "LSLpl $dst.hi,$src1.lo,$dst.hi \n\t" 6200 "RSBmi $dst.hi,$dst.hi,0 \n\t" 6201 "LSRmi $dst.hi,$src1.lo,$dst.hi" %} 6202 6203 ins_encode %{ 6204 // $src1$$Register and $dst$$Register->successor() can't be the same 6205 __ subs($dst$$Register->successor(), $src2$$Register, 32); 6206 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register, lsl, $dst$$Register->successor()), pl); 6207 __ rsb($dst$$Register->successor(), $dst$$Register->successor(), 0, mi); 6208 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register, lsr, $dst$$Register->successor()), mi); 6209 %} 6210 ins_pipe(ialu_reg_reg); 6211%} 6212 6213instruct shlL_reg_reg(iRegL dst, iRegL src1, iRegI src2) %{ 6214 match(Set dst (LShiftL src1 src2)); 6215 6216 expand %{ 6217 flagsReg ccr; 6218 shlL_reg_reg_overlap(dst, src1, src2, ccr); 6219 shlL_reg_reg_merge_hi(dst, src1, src2); 6220 shlL_reg_reg_merge_lo(dst, src1, src2); 6221 %} 6222%} 6223 6224// Register Shift Left Immediate 6225instruct shlL_reg_imm6(iRegL dst, iRegL src1, immU6Big src2) %{ 6226 match(Set dst (LShiftL src1 src2)); 6227 6228 size(8); 6229 format %{ "LSL $dst.hi,$src1.lo,$src2-32\t! or mov if $src2==32\n\t" 6230 "MOV $dst.lo, 0" %} 6231 ins_encode %{ 6232 if ($src2$$constant == 32) { 6233 __ mov($dst$$Register->successor(), $src1$$Register); 6234 } else { 6235 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register, lsl, $src2$$constant-32)); 6236 } 6237 __ mov($dst$$Register, 0); 6238 %} 6239 ins_pipe(ialu_reg_imm); 6240%} 6241 6242instruct shlL_reg_imm5(iRegL dst, iRegL src1, immU5 src2) %{ 6243 match(Set dst (LShiftL src1 src2)); 6244 6245 size(12); 6246 format %{ "LSL $dst.hi,$src1.lo,$src2\n\t" 6247 "OR $dst.hi, $dst.hi, $src1.lo >> 32-$src2\n\t" 6248 "LSL $dst.lo,$src1.lo,$src2" %} 6249 ins_encode %{ 6250 // The order of the following 3 instructions matters: src1.lo and 6251 // dst.hi can't overlap but src.hi and dst.hi can. 6252 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsl, $src2$$constant)); 6253 __ orr($dst$$Register->successor(), $dst$$Register->successor(), AsmOperand($src1$$Register, lsr, 32-$src2$$constant)); 6254 __ mov($dst$$Register, AsmOperand($src1$$Register, lsl, $src2$$constant)); 6255 %} 6256 ins_pipe(ialu_reg_imm); 6257%} 6258 6259// Register Arithmetic Shift Right 6260instruct sarI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 6261 match(Set dst (RShiftI src1 src2)); 6262 size(4); 6263 format %{ "ASR $dst,$src1,$src2\t! int" %} 6264 ins_encode %{ 6265 __ mov($dst$$Register, AsmOperand($src1$$Register, asr, $src2$$Register)); 6266 %} 6267 ins_pipe(ialu_reg_reg); 6268%} 6269 6270// Register Arithmetic Shift Right Immediate 6271instruct sarI_reg_imm5(iRegI dst, iRegI src1, immU5 src2) %{ 6272 match(Set dst (RShiftI src1 src2)); 6273 6274 size(4); 6275 format %{ "ASR $dst,$src1,$src2" %} 6276 ins_encode %{ 6277 __ mov($dst$$Register, AsmOperand($src1$$Register, asr, $src2$$constant)); 6278 %} 6279 ins_pipe(ialu_reg_imm); 6280%} 6281 6282// Register Shift Right Arithmetic Long 6283instruct sarL_reg_reg_merge_lo(iRegL dst, iRegL src1, iRegI src2) %{ 6284 effect(USE_DEF dst, USE src1, USE src2); 6285 size(4); 6286 format %{ "OR $dst.lo,$dst.lo,($src1.lo >> $src2)" %} 6287 ins_encode %{ 6288 __ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register)); 6289 %} 6290 ins_pipe(ialu_reg_reg); 6291%} 6292 6293instruct sarL_reg_reg_merge_hi(iRegL dst, iRegL src1, iRegI src2) %{ 6294 effect(USE_DEF dst, USE src1, USE src2); 6295 size(4); 6296 format %{ "ASR $dst.hi,$src1.hi,$src2 \n\t" %} 6297 ins_encode %{ 6298 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), asr, $src2$$Register)); 6299 %} 6300 ins_pipe(ialu_reg_reg); 6301%} 6302 6303instruct sarL_reg_reg_overlap(iRegL dst, iRegL src1, iRegI src2, flagsReg ccr) %{ 6304 effect(DEF dst, USE src1, USE src2, KILL ccr); 6305 size(16); 6306 format %{ "SUBS $dst.lo,$src2,32 \n\t" 6307 "ASRpl $dst.lo,$src1.hi,$dst.lo \n\t" 6308 "RSBmi $dst.lo,$dst.lo,0 \n\t" 6309 "LSLmi $dst.lo,$src1.hi,$dst.lo" %} 6310 6311 ins_encode %{ 6312 // $src1$$Register->successor() and $dst$$Register can't be the same 6313 __ subs($dst$$Register, $src2$$Register, 32); 6314 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), asr, $dst$$Register), pl); 6315 __ rsb($dst$$Register, $dst$$Register, 0, mi); 6316 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsl, $dst$$Register), mi); 6317 %} 6318 ins_pipe(ialu_reg_reg); 6319%} 6320 6321instruct sarL_reg_reg(iRegL dst, iRegL src1, iRegI src2) %{ 6322 match(Set dst (RShiftL src1 src2)); 6323 6324 expand %{ 6325 flagsReg ccr; 6326 sarL_reg_reg_overlap(dst, src1, src2, ccr); 6327 sarL_reg_reg_merge_lo(dst, src1, src2); 6328 sarL_reg_reg_merge_hi(dst, src1, src2); 6329 %} 6330%} 6331 6332// Register Shift Left Immediate 6333instruct sarL_reg_imm6(iRegL dst, iRegL src1, immU6Big src2) %{ 6334 match(Set dst (RShiftL src1 src2)); 6335 6336 size(8); 6337 format %{ "ASR $dst.lo,$src1.hi,$src2-32\t! or mov if $src2==32\n\t" 6338 "ASR $dst.hi,$src1.hi, $src2" %} 6339 ins_encode %{ 6340 if ($src2$$constant == 32) { 6341 __ mov($dst$$Register, $src1$$Register->successor()); 6342 } else{ 6343 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), asr, $src2$$constant-32)); 6344 } 6345 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), asr, 0)); 6346 %} 6347 6348 ins_pipe(ialu_reg_imm); 6349%} 6350 6351instruct sarL_reg_imm5(iRegL dst, iRegL src1, immU5 src2) %{ 6352 match(Set dst (RShiftL src1 src2)); 6353 size(12); 6354 format %{ "LSR $dst.lo,$src1.lo,$src2\n\t" 6355 "OR $dst.lo, $dst.lo, $src1.hi << 32-$src2\n\t" 6356 "ASR $dst.hi,$src1.hi,$src2" %} 6357 ins_encode %{ 6358 // The order of the following 3 instructions matters: src1.lo and 6359 // dst.hi can't overlap but src.hi and dst.hi can. 6360 __ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant)); 6361 __ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register->successor(), lsl, 32-$src2$$constant)); 6362 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), asr, $src2$$constant)); 6363 %} 6364 ins_pipe(ialu_reg_imm); 6365%} 6366 6367// Register Shift Right 6368instruct shrI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 6369 match(Set dst (URShiftI src1 src2)); 6370 size(4); 6371 format %{ "LSR $dst,$src1,$src2\t! int" %} 6372 ins_encode %{ 6373 __ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register)); 6374 %} 6375 ins_pipe(ialu_reg_reg); 6376%} 6377 6378// Register Shift Right Immediate 6379instruct shrI_reg_imm5(iRegI dst, iRegI src1, immU5 src2) %{ 6380 match(Set dst (URShiftI src1 src2)); 6381 6382 size(4); 6383 format %{ "LSR $dst,$src1,$src2" %} 6384 ins_encode %{ 6385 __ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant)); 6386 %} 6387 ins_pipe(ialu_reg_imm); 6388%} 6389 6390// Register Shift Right 6391instruct shrL_reg_reg_merge_lo(iRegL dst, iRegL src1, iRegI src2) %{ 6392 effect(USE_DEF dst, USE src1, USE src2); 6393 size(4); 6394 format %{ "OR $dst.lo,$dst,($src1.lo >>> $src2)" %} 6395 ins_encode %{ 6396 __ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register)); 6397 %} 6398 ins_pipe(ialu_reg_reg); 6399%} 6400 6401instruct shrL_reg_reg_merge_hi(iRegL dst, iRegL src1, iRegI src2) %{ 6402 effect(USE_DEF dst, USE src1, USE src2); 6403 size(4); 6404 format %{ "LSR $dst.hi,$src1.hi,$src2 \n\t" %} 6405 ins_encode %{ 6406 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsr, $src2$$Register)); 6407 %} 6408 ins_pipe(ialu_reg_reg); 6409%} 6410 6411instruct shrL_reg_reg_overlap(iRegL dst, iRegL src1, iRegI src2, flagsReg ccr) %{ 6412 effect(DEF dst, USE src1, USE src2, KILL ccr); 6413 size(16); 6414 format %{ "SUBS $dst,$src2,32 \n\t" 6415 "LSRpl $dst,$src1.hi,$dst \n\t" 6416 "RSBmi $dst,$dst,0 \n\t" 6417 "LSLmi $dst,$src1.hi,$dst" %} 6418 6419 ins_encode %{ 6420 // $src1$$Register->successor() and $dst$$Register can't be the same 6421 __ subs($dst$$Register, $src2$$Register, 32); 6422 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsr, $dst$$Register), pl); 6423 __ rsb($dst$$Register, $dst$$Register, 0, mi); 6424 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsl, $dst$$Register), mi); 6425 %} 6426 ins_pipe(ialu_reg_reg); 6427%} 6428 6429instruct shrL_reg_reg(iRegL dst, iRegL src1, iRegI src2) %{ 6430 match(Set dst (URShiftL src1 src2)); 6431 6432 expand %{ 6433 flagsReg ccr; 6434 shrL_reg_reg_overlap(dst, src1, src2, ccr); 6435 shrL_reg_reg_merge_lo(dst, src1, src2); 6436 shrL_reg_reg_merge_hi(dst, src1, src2); 6437 %} 6438%} 6439 6440// Register Shift Right Immediate 6441instruct shrL_reg_imm6(iRegL dst, iRegL src1, immU6Big src2) %{ 6442 match(Set dst (URShiftL src1 src2)); 6443 6444 size(8); 6445 format %{ "LSR $dst.lo,$src1.hi,$src2-32\t! or mov if $src2==32\n\t" 6446 "MOV $dst.hi, 0" %} 6447 ins_encode %{ 6448 if ($src2$$constant == 32) { 6449 __ mov($dst$$Register, $src1$$Register->successor()); 6450 } else { 6451 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsr, $src2$$constant-32)); 6452 } 6453 __ mov($dst$$Register->successor(), 0); 6454 %} 6455 6456 ins_pipe(ialu_reg_imm); 6457%} 6458 6459instruct shrL_reg_imm5(iRegL dst, iRegL src1, immU5 src2) %{ 6460 match(Set dst (URShiftL src1 src2)); 6461 6462 size(12); 6463 format %{ "LSR $dst.lo,$src1.lo,$src2\n\t" 6464 "OR $dst.lo, $dst.lo, $src1.hi << 32-$src2\n\t" 6465 "LSR $dst.hi,$src1.hi,$src2" %} 6466 ins_encode %{ 6467 // The order of the following 3 instructions matters: src1.lo and 6468 // dst.hi can't overlap but src.hi and dst.hi can. 6469 __ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant)); 6470 __ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register->successor(), lsl, 32-$src2$$constant)); 6471 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsr, $src2$$constant)); 6472 %} 6473 ins_pipe(ialu_reg_imm); 6474%} 6475 6476 6477instruct shrP_reg_imm5(iRegX dst, iRegP src1, immU5 src2) %{ 6478 match(Set dst (URShiftI (CastP2X src1) src2)); 6479 size(4); 6480 format %{ "LSR $dst,$src1,$src2\t! Cast ptr $src1 to int and shift" %} 6481 ins_encode %{ 6482 __ logical_shift_right($dst$$Register, $src1$$Register, $src2$$constant); 6483 %} 6484 ins_pipe(ialu_reg_imm); 6485%} 6486 6487//----------Floating Point Arithmetic Instructions----------------------------- 6488 6489// Add float single precision 6490instruct addF_reg_reg(regF dst, regF src1, regF src2) %{ 6491 match(Set dst (AddF src1 src2)); 6492 6493 size(4); 6494 format %{ "FADDS $dst,$src1,$src2" %} 6495 ins_encode %{ 6496 __ add_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 6497 %} 6498 6499 ins_pipe(faddF_reg_reg); 6500%} 6501 6502// Add float double precision 6503instruct addD_reg_reg(regD dst, regD src1, regD src2) %{ 6504 match(Set dst (AddD src1 src2)); 6505 6506 size(4); 6507 format %{ "FADDD $dst,$src1,$src2" %} 6508 ins_encode %{ 6509 __ add_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 6510 %} 6511 6512 ins_pipe(faddD_reg_reg); 6513%} 6514 6515// Sub float single precision 6516instruct subF_reg_reg(regF dst, regF src1, regF src2) %{ 6517 match(Set dst (SubF src1 src2)); 6518 6519 size(4); 6520 format %{ "FSUBS $dst,$src1,$src2" %} 6521 ins_encode %{ 6522 __ sub_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 6523 %} 6524 ins_pipe(faddF_reg_reg); 6525%} 6526 6527// Sub float double precision 6528instruct subD_reg_reg(regD dst, regD src1, regD src2) %{ 6529 match(Set dst (SubD src1 src2)); 6530 6531 size(4); 6532 format %{ "FSUBD $dst,$src1,$src2" %} 6533 ins_encode %{ 6534 __ sub_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 6535 %} 6536 ins_pipe(faddD_reg_reg); 6537%} 6538 6539// Mul float single precision 6540instruct mulF_reg_reg(regF dst, regF src1, regF src2) %{ 6541 match(Set dst (MulF src1 src2)); 6542 6543 size(4); 6544 format %{ "FMULS $dst,$src1,$src2" %} 6545 ins_encode %{ 6546 __ mul_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 6547 %} 6548 6549 ins_pipe(fmulF_reg_reg); 6550%} 6551 6552// Mul float double precision 6553instruct mulD_reg_reg(regD dst, regD src1, regD src2) %{ 6554 match(Set dst (MulD src1 src2)); 6555 6556 size(4); 6557 format %{ "FMULD $dst,$src1,$src2" %} 6558 ins_encode %{ 6559 __ mul_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 6560 %} 6561 6562 ins_pipe(fmulD_reg_reg); 6563%} 6564 6565// Div float single precision 6566instruct divF_reg_reg(regF dst, regF src1, regF src2) %{ 6567 match(Set dst (DivF src1 src2)); 6568 6569 size(4); 6570 format %{ "FDIVS $dst,$src1,$src2" %} 6571 ins_encode %{ 6572 __ div_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 6573 %} 6574 6575 ins_pipe(fdivF_reg_reg); 6576%} 6577 6578// Div float double precision 6579instruct divD_reg_reg(regD dst, regD src1, regD src2) %{ 6580 match(Set dst (DivD src1 src2)); 6581 6582 size(4); 6583 format %{ "FDIVD $dst,$src1,$src2" %} 6584 ins_encode %{ 6585 __ div_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 6586 %} 6587 6588 ins_pipe(fdivD_reg_reg); 6589%} 6590 6591// Absolute float double precision 6592instruct absD_reg(regD dst, regD src) %{ 6593 match(Set dst (AbsD src)); 6594 6595 size(4); 6596 format %{ "FABSd $dst,$src" %} 6597 ins_encode %{ 6598 __ abs_double($dst$$FloatRegister, $src$$FloatRegister); 6599 %} 6600 ins_pipe(faddD_reg); 6601%} 6602 6603// Absolute float single precision 6604instruct absF_reg(regF dst, regF src) %{ 6605 match(Set dst (AbsF src)); 6606 format %{ "FABSs $dst,$src" %} 6607 ins_encode %{ 6608 __ abs_float($dst$$FloatRegister, $src$$FloatRegister); 6609 %} 6610 ins_pipe(faddF_reg); 6611%} 6612 6613instruct negF_reg(regF dst, regF src) %{ 6614 match(Set dst (NegF src)); 6615 6616 size(4); 6617 format %{ "FNEGs $dst,$src" %} 6618 ins_encode %{ 6619 __ neg_float($dst$$FloatRegister, $src$$FloatRegister); 6620 %} 6621 ins_pipe(faddF_reg); 6622%} 6623 6624instruct negD_reg(regD dst, regD src) %{ 6625 match(Set dst (NegD src)); 6626 6627 format %{ "FNEGd $dst,$src" %} 6628 ins_encode %{ 6629 __ neg_double($dst$$FloatRegister, $src$$FloatRegister); 6630 %} 6631 ins_pipe(faddD_reg); 6632%} 6633 6634// Sqrt float double precision 6635instruct sqrtF_reg_reg(regF dst, regF src) %{ 6636 match(Set dst (ConvD2F (SqrtD (ConvF2D src)))); 6637 6638 size(4); 6639 format %{ "FSQRTS $dst,$src" %} 6640 ins_encode %{ 6641 __ sqrt_float($dst$$FloatRegister, $src$$FloatRegister); 6642 %} 6643 ins_pipe(fdivF_reg_reg); 6644%} 6645 6646// Sqrt float double precision 6647instruct sqrtD_reg_reg(regD dst, regD src) %{ 6648 match(Set dst (SqrtD src)); 6649 6650 size(4); 6651 format %{ "FSQRTD $dst,$src" %} 6652 ins_encode %{ 6653 __ sqrt_double($dst$$FloatRegister, $src$$FloatRegister); 6654 %} 6655 ins_pipe(fdivD_reg_reg); 6656%} 6657 6658//----------Logical Instructions----------------------------------------------- 6659// And Instructions 6660// Register And 6661instruct andI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 6662 match(Set dst (AndI src1 src2)); 6663 6664 size(4); 6665 format %{ "and_32 $dst,$src1,$src2" %} 6666 ins_encode %{ 6667 __ and_32($dst$$Register, $src1$$Register, $src2$$Register); 6668 %} 6669 ins_pipe(ialu_reg_reg); 6670%} 6671 6672instruct andshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 6673 match(Set dst (AndI src1 (LShiftI src2 src3))); 6674 6675 size(4); 6676 format %{ "AND $dst,$src1,$src2<<$src3" %} 6677 ins_encode %{ 6678 __ andr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register)); 6679 %} 6680 ins_pipe(ialu_reg_reg); 6681%} 6682 6683instruct andshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 6684 match(Set dst (AndI src1 (LShiftI src2 src3))); 6685 6686 size(4); 6687 format %{ "and_32 $dst,$src1,$src2<<$src3" %} 6688 ins_encode %{ 6689 __ and_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant)); 6690 %} 6691 ins_pipe(ialu_reg_reg); 6692%} 6693 6694instruct andsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 6695 match(Set dst (AndI src1 (RShiftI src2 src3))); 6696 6697 size(4); 6698 format %{ "AND $dst,$src1,$src2>>$src3" %} 6699 ins_encode %{ 6700 __ andr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register)); 6701 %} 6702 ins_pipe(ialu_reg_reg); 6703%} 6704 6705instruct andsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 6706 match(Set dst (AndI src1 (RShiftI src2 src3))); 6707 6708 size(4); 6709 format %{ "and_32 $dst,$src1,$src2>>$src3" %} 6710 ins_encode %{ 6711 __ and_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant)); 6712 %} 6713 ins_pipe(ialu_reg_reg); 6714%} 6715 6716instruct andshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 6717 match(Set dst (AndI src1 (URShiftI src2 src3))); 6718 6719 size(4); 6720 format %{ "AND $dst,$src1,$src2>>>$src3" %} 6721 ins_encode %{ 6722 __ andr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register)); 6723 %} 6724 ins_pipe(ialu_reg_reg); 6725%} 6726 6727instruct andshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 6728 match(Set dst (AndI src1 (URShiftI src2 src3))); 6729 6730 size(4); 6731 format %{ "and_32 $dst,$src1,$src2>>>$src3" %} 6732 ins_encode %{ 6733 __ and_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant)); 6734 %} 6735 ins_pipe(ialu_reg_reg); 6736%} 6737 6738// Immediate And 6739instruct andI_reg_limm(iRegI dst, iRegI src1, limmI src2) %{ 6740 match(Set dst (AndI src1 src2)); 6741 6742 size(4); 6743 format %{ "and_32 $dst,$src1,$src2\t! int" %} 6744 ins_encode %{ 6745 __ and_32($dst$$Register, $src1$$Register, $src2$$constant); 6746 %} 6747 ins_pipe(ialu_reg_imm); 6748%} 6749 6750instruct andI_reg_limmn(iRegI dst, iRegI src1, limmIn src2) %{ 6751 match(Set dst (AndI src1 src2)); 6752 6753 size(4); 6754 format %{ "bic $dst,$src1,~$src2\t! int" %} 6755 ins_encode %{ 6756 __ bic($dst$$Register, $src1$$Register, ~$src2$$constant); 6757 %} 6758 ins_pipe(ialu_reg_imm); 6759%} 6760 6761// Register And Long 6762instruct andL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{ 6763 match(Set dst (AndL src1 src2)); 6764 6765 ins_cost(DEFAULT_COST); 6766 size(8); 6767 format %{ "AND $dst,$src1,$src2\t! long" %} 6768 ins_encode %{ 6769 __ andr($dst$$Register, $src1$$Register, $src2$$Register); 6770 __ andr($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor()); 6771 %} 6772 ins_pipe(ialu_reg_reg); 6773%} 6774 6775// TODO: try immLRot2 instead, (0, $con$$constant) becomes 6776// (hi($con$$constant), lo($con$$constant)) becomes 6777instruct andL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con) %{ 6778 match(Set dst (AndL src1 con)); 6779 ins_cost(DEFAULT_COST); 6780 size(8); 6781 format %{ "AND $dst,$src1,$con\t! long" %} 6782 ins_encode %{ 6783 __ andr($dst$$Register, $src1$$Register, $con$$constant); 6784 __ andr($dst$$Register->successor(), $src1$$Register->successor(), 0); 6785 %} 6786 ins_pipe(ialu_reg_imm); 6787%} 6788 6789// Or Instructions 6790// Register Or 6791instruct orI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 6792 match(Set dst (OrI src1 src2)); 6793 6794 size(4); 6795 format %{ "orr_32 $dst,$src1,$src2\t! int" %} 6796 ins_encode %{ 6797 __ orr_32($dst$$Register, $src1$$Register, $src2$$Register); 6798 %} 6799 ins_pipe(ialu_reg_reg); 6800%} 6801 6802instruct orshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 6803 match(Set dst (OrI src1 (LShiftI src2 src3))); 6804 6805 size(4); 6806 format %{ "OR $dst,$src1,$src2<<$src3" %} 6807 ins_encode %{ 6808 __ orr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register)); 6809 %} 6810 ins_pipe(ialu_reg_reg); 6811%} 6812 6813instruct orshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 6814 match(Set dst (OrI src1 (LShiftI src2 src3))); 6815 6816 size(4); 6817 format %{ "orr_32 $dst,$src1,$src2<<$src3" %} 6818 ins_encode %{ 6819 __ orr_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant)); 6820 %} 6821 ins_pipe(ialu_reg_reg); 6822%} 6823 6824instruct orsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 6825 match(Set dst (OrI src1 (RShiftI src2 src3))); 6826 6827 size(4); 6828 format %{ "OR $dst,$src1,$src2>>$src3" %} 6829 ins_encode %{ 6830 __ orr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register)); 6831 %} 6832 ins_pipe(ialu_reg_reg); 6833%} 6834 6835instruct orsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 6836 match(Set dst (OrI src1 (RShiftI src2 src3))); 6837 6838 size(4); 6839 format %{ "orr_32 $dst,$src1,$src2>>$src3" %} 6840 ins_encode %{ 6841 __ orr_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant)); 6842 %} 6843 ins_pipe(ialu_reg_reg); 6844%} 6845 6846instruct orshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 6847 match(Set dst (OrI src1 (URShiftI src2 src3))); 6848 6849 size(4); 6850 format %{ "OR $dst,$src1,$src2>>>$src3" %} 6851 ins_encode %{ 6852 __ orr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register)); 6853 %} 6854 ins_pipe(ialu_reg_reg); 6855%} 6856 6857instruct orshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 6858 match(Set dst (OrI src1 (URShiftI src2 src3))); 6859 6860 size(4); 6861 format %{ "orr_32 $dst,$src1,$src2>>>$src3" %} 6862 ins_encode %{ 6863 __ orr_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant)); 6864 %} 6865 ins_pipe(ialu_reg_reg); 6866%} 6867 6868// Immediate Or 6869instruct orI_reg_limm(iRegI dst, iRegI src1, limmI src2) %{ 6870 match(Set dst (OrI src1 src2)); 6871 6872 size(4); 6873 format %{ "orr_32 $dst,$src1,$src2" %} 6874 ins_encode %{ 6875 __ orr_32($dst$$Register, $src1$$Register, $src2$$constant); 6876 %} 6877 ins_pipe(ialu_reg_imm); 6878%} 6879// TODO: orn_32 with limmIn 6880 6881// Register Or Long 6882instruct orL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{ 6883 match(Set dst (OrL src1 src2)); 6884 6885 ins_cost(DEFAULT_COST); 6886 size(8); 6887 format %{ "OR $dst.lo,$src1.lo,$src2.lo\t! long\n\t" 6888 "OR $dst.hi,$src1.hi,$src2.hi" %} 6889 ins_encode %{ 6890 __ orr($dst$$Register, $src1$$Register, $src2$$Register); 6891 __ orr($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor()); 6892 %} 6893 ins_pipe(ialu_reg_reg); 6894%} 6895 6896// TODO: try immLRot2 instead, (0, $con$$constant) becomes 6897// (hi($con$$constant), lo($con$$constant)) becomes 6898instruct orL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con) %{ 6899 match(Set dst (OrL src1 con)); 6900 ins_cost(DEFAULT_COST); 6901 size(8); 6902 format %{ "OR $dst.lo,$src1.lo,$con\t! long\n\t" 6903 "OR $dst.hi,$src1.hi,$con" %} 6904 ins_encode %{ 6905 __ orr($dst$$Register, $src1$$Register, $con$$constant); 6906 __ orr($dst$$Register->successor(), $src1$$Register->successor(), 0); 6907 %} 6908 ins_pipe(ialu_reg_imm); 6909%} 6910 6911#ifdef TODO 6912// Use SPRegP to match Rthread (TLS register) without spilling. 6913// Use store_ptr_RegP to match Rthread (TLS register) without spilling. 6914// Use sp_ptr_RegP to match Rthread (TLS register) without spilling. 6915instruct orI_reg_castP2X(iRegI dst, iRegI src1, sp_ptr_RegP src2) %{ 6916 match(Set dst (OrI src1 (CastP2X src2))); 6917 size(4); 6918 format %{ "OR $dst,$src1,$src2" %} 6919 ins_encode %{ 6920 __ orr($dst$$Register, $src1$$Register, $src2$$Register); 6921 %} 6922 ins_pipe(ialu_reg_reg); 6923%} 6924#endif 6925 6926// Xor Instructions 6927// Register Xor 6928instruct xorI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 6929 match(Set dst (XorI src1 src2)); 6930 6931 size(4); 6932 format %{ "eor_32 $dst,$src1,$src2" %} 6933 ins_encode %{ 6934 __ eor_32($dst$$Register, $src1$$Register, $src2$$Register); 6935 %} 6936 ins_pipe(ialu_reg_reg); 6937%} 6938 6939instruct xorshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 6940 match(Set dst (XorI src1 (LShiftI src2 src3))); 6941 6942 size(4); 6943 format %{ "XOR $dst,$src1,$src2<<$src3" %} 6944 ins_encode %{ 6945 __ eor($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register)); 6946 %} 6947 ins_pipe(ialu_reg_reg); 6948%} 6949 6950instruct xorshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 6951 match(Set dst (XorI src1 (LShiftI src2 src3))); 6952 6953 size(4); 6954 format %{ "eor_32 $dst,$src1,$src2<<$src3" %} 6955 ins_encode %{ 6956 __ eor_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant)); 6957 %} 6958 ins_pipe(ialu_reg_reg); 6959%} 6960 6961instruct xorsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 6962 match(Set dst (XorI src1 (RShiftI src2 src3))); 6963 6964 size(4); 6965 format %{ "XOR $dst,$src1,$src2>>$src3" %} 6966 ins_encode %{ 6967 __ eor($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register)); 6968 %} 6969 ins_pipe(ialu_reg_reg); 6970%} 6971 6972instruct xorsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 6973 match(Set dst (XorI src1 (RShiftI src2 src3))); 6974 6975 size(4); 6976 format %{ "eor_32 $dst,$src1,$src2>>$src3" %} 6977 ins_encode %{ 6978 __ eor_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant)); 6979 %} 6980 ins_pipe(ialu_reg_reg); 6981%} 6982 6983instruct xorshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 6984 match(Set dst (XorI src1 (URShiftI src2 src3))); 6985 6986 size(4); 6987 format %{ "XOR $dst,$src1,$src2>>>$src3" %} 6988 ins_encode %{ 6989 __ eor($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register)); 6990 %} 6991 ins_pipe(ialu_reg_reg); 6992%} 6993 6994instruct xorshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 6995 match(Set dst (XorI src1 (URShiftI src2 src3))); 6996 6997 size(4); 6998 format %{ "eor_32 $dst,$src1,$src2>>>$src3" %} 6999 ins_encode %{ 7000 __ eor_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant)); 7001 %} 7002 ins_pipe(ialu_reg_reg); 7003%} 7004 7005// Immediate Xor 7006instruct xorI_reg_imm(iRegI dst, iRegI src1, limmI src2) %{ 7007 match(Set dst (XorI src1 src2)); 7008 7009 size(4); 7010 format %{ "eor_32 $dst,$src1,$src2" %} 7011 ins_encode %{ 7012 __ eor_32($dst$$Register, $src1$$Register, $src2$$constant); 7013 %} 7014 ins_pipe(ialu_reg_imm); 7015%} 7016 7017// Register Xor Long 7018instruct xorL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{ 7019 match(Set dst (XorL src1 src2)); 7020 ins_cost(DEFAULT_COST); 7021 size(8); 7022 format %{ "XOR $dst.hi,$src1.hi,$src2.hi\t! long\n\t" 7023 "XOR $dst.lo,$src1.lo,$src2.lo\t! long" %} 7024 ins_encode %{ 7025 __ eor($dst$$Register, $src1$$Register, $src2$$Register); 7026 __ eor($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor()); 7027 %} 7028 ins_pipe(ialu_reg_reg); 7029%} 7030 7031// TODO: try immLRot2 instead, (0, $con$$constant) becomes 7032// (hi($con$$constant), lo($con$$constant)) becomes 7033instruct xorL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con) %{ 7034 match(Set dst (XorL src1 con)); 7035 ins_cost(DEFAULT_COST); 7036 size(8); 7037 format %{ "XOR $dst.hi,$src1.hi,$con\t! long\n\t" 7038 "XOR $dst.lo,$src1.lo,0\t! long" %} 7039 ins_encode %{ 7040 __ eor($dst$$Register, $src1$$Register, $con$$constant); 7041 __ eor($dst$$Register->successor(), $src1$$Register->successor(), 0); 7042 %} 7043 ins_pipe(ialu_reg_imm); 7044%} 7045 7046//----------Convert to Boolean------------------------------------------------- 7047instruct convI2B( iRegI dst, iRegI src, flagsReg ccr ) %{ 7048 match(Set dst (Conv2B src)); 7049 effect(KILL ccr); 7050 size(12); 7051 ins_cost(DEFAULT_COST*2); 7052 format %{ "TST $src,$src \n\t" 7053 "MOV $dst, 0 \n\t" 7054 "MOV.ne $dst, 1" %} 7055 ins_encode %{ // FIXME: can do better? 7056 __ tst($src$$Register, $src$$Register); 7057 __ mov($dst$$Register, 0); 7058 __ mov($dst$$Register, 1, ne); 7059 %} 7060 ins_pipe(ialu_reg_ialu); 7061%} 7062 7063instruct convP2B( iRegI dst, iRegP src, flagsReg ccr ) %{ 7064 match(Set dst (Conv2B src)); 7065 effect(KILL ccr); 7066 size(12); 7067 ins_cost(DEFAULT_COST*2); 7068 format %{ "TST $src,$src \n\t" 7069 "MOV $dst, 0 \n\t" 7070 "MOV.ne $dst, 1" %} 7071 ins_encode %{ 7072 __ tst($src$$Register, $src$$Register); 7073 __ mov($dst$$Register, 0); 7074 __ mov($dst$$Register, 1, ne); 7075 %} 7076 ins_pipe(ialu_reg_ialu); 7077%} 7078 7079instruct cmpLTMask_reg_reg( iRegI dst, iRegI p, iRegI q, flagsReg ccr ) %{ 7080 match(Set dst (CmpLTMask p q)); 7081 effect( KILL ccr ); 7082 ins_cost(DEFAULT_COST*3); 7083 format %{ "CMP $p,$q\n\t" 7084 "MOV $dst, #0\n\t" 7085 "MOV.lt $dst, #-1" %} 7086 ins_encode %{ 7087 __ cmp($p$$Register, $q$$Register); 7088 __ mov($dst$$Register, 0); 7089 __ mvn($dst$$Register, 0, lt); 7090 %} 7091 ins_pipe(ialu_reg_reg_ialu); 7092%} 7093 7094instruct cmpLTMask_reg_imm( iRegI dst, iRegI p, aimmI q, flagsReg ccr ) %{ 7095 match(Set dst (CmpLTMask p q)); 7096 effect( KILL ccr ); 7097 ins_cost(DEFAULT_COST*3); 7098 format %{ "CMP $p,$q\n\t" 7099 "MOV $dst, #0\n\t" 7100 "MOV.lt $dst, #-1" %} 7101 ins_encode %{ 7102 __ cmp($p$$Register, $q$$constant); 7103 __ mov($dst$$Register, 0); 7104 __ mvn($dst$$Register, 0, lt); 7105 %} 7106 ins_pipe(ialu_reg_reg_ialu); 7107%} 7108 7109instruct cadd_cmpLTMask3( iRegI p, iRegI q, iRegI y, iRegI z, flagsReg ccr ) %{ 7110 match(Set z (AddI (AndI (CmpLTMask p q) y) z)); 7111 effect( KILL ccr ); 7112 ins_cost(DEFAULT_COST*2); 7113 format %{ "CMP $p,$q\n\t" 7114 "ADD.lt $z,$y,$z" %} 7115 ins_encode %{ 7116 __ cmp($p$$Register, $q$$Register); 7117 __ add($z$$Register, $y$$Register, $z$$Register, lt); 7118 %} 7119 ins_pipe( cadd_cmpltmask ); 7120%} 7121 7122// FIXME: remove unused "dst" 7123instruct cadd_cmpLTMask4( iRegI dst, iRegI p, aimmI q, iRegI y, iRegI z, flagsReg ccr ) %{ 7124 match(Set z (AddI (AndI (CmpLTMask p q) y) z)); 7125 effect( KILL ccr ); 7126 ins_cost(DEFAULT_COST*2); 7127 format %{ "CMP $p,$q\n\t" 7128 "ADD.lt $z,$y,$z" %} 7129 ins_encode %{ 7130 __ cmp($p$$Register, $q$$constant); 7131 __ add($z$$Register, $y$$Register, $z$$Register, lt); 7132 %} 7133 ins_pipe( cadd_cmpltmask ); 7134%} 7135 7136instruct cadd_cmpLTMask( iRegI p, iRegI q, iRegI y, flagsReg ccr ) %{ 7137 match(Set p (AddI (AndI (CmpLTMask p q) y) (SubI p q))); 7138 effect( KILL ccr ); 7139 ins_cost(DEFAULT_COST*2); 7140 format %{ "SUBS $p,$p,$q\n\t" 7141 "ADD.lt $p,$y,$p" %} 7142 ins_encode %{ 7143 __ subs($p$$Register, $p$$Register, $q$$Register); 7144 __ add($p$$Register, $y$$Register, $p$$Register, lt); 7145 %} 7146 ins_pipe( cadd_cmpltmask ); 7147%} 7148 7149//----------Arithmetic Conversion Instructions--------------------------------- 7150// The conversions operations are all Alpha sorted. Please keep it that way! 7151 7152instruct convD2F_reg(regF dst, regD src) %{ 7153 match(Set dst (ConvD2F src)); 7154 size(4); 7155 format %{ "FCVTSD $dst,$src" %} 7156 ins_encode %{ 7157 __ convert_d2f($dst$$FloatRegister, $src$$FloatRegister); 7158 %} 7159 ins_pipe(fcvtD2F); 7160%} 7161 7162// Convert a double to an int in a float register. 7163// If the double is a NAN, stuff a zero in instead. 7164 7165instruct convD2I_reg_reg(iRegI dst, regD src, regF tmp) %{ 7166 match(Set dst (ConvD2I src)); 7167 effect( TEMP tmp ); 7168 ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME 7169 format %{ "FTOSIZD $tmp,$src\n\t" 7170 "FMRS $dst, $tmp" %} 7171 ins_encode %{ 7172 __ ftosizd($tmp$$FloatRegister, $src$$FloatRegister); 7173 __ fmrs($dst$$Register, $tmp$$FloatRegister); 7174 %} 7175 ins_pipe(fcvtD2I); 7176%} 7177 7178// Convert a double to a long in a double register. 7179// If the double is a NAN, stuff a zero in instead. 7180 7181// Double to Long conversion 7182instruct convD2L_reg(R0R1RegL dst, regD src) %{ 7183 match(Set dst (ConvD2L src)); 7184 effect(CALL); 7185 ins_cost(MEMORY_REF_COST); // FIXME 7186 format %{ "convD2L $dst,$src\t ! call to SharedRuntime::d2l" %} 7187 ins_encode %{ 7188#ifndef __ABI_HARD__ 7189 __ fmrrd($dst$$Register, $dst$$Register->successor(), $src$$FloatRegister); 7190#else 7191 if ($src$$FloatRegister != D0) { 7192 __ mov_double(D0, $src$$FloatRegister); 7193 } 7194#endif 7195 address target = CAST_FROM_FN_PTR(address, SharedRuntime::d2l); 7196 __ call(target, relocInfo::runtime_call_type); 7197 %} 7198 ins_pipe(fcvtD2L); 7199%} 7200 7201instruct convF2D_reg(regD dst, regF src) %{ 7202 match(Set dst (ConvF2D src)); 7203 size(4); 7204 format %{ "FCVTDS $dst,$src" %} 7205 ins_encode %{ 7206 __ convert_f2d($dst$$FloatRegister, $src$$FloatRegister); 7207 %} 7208 ins_pipe(fcvtF2D); 7209%} 7210 7211instruct convF2I_reg_reg(iRegI dst, regF src, regF tmp) %{ 7212 match(Set dst (ConvF2I src)); 7213 effect( TEMP tmp ); 7214 ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME 7215 size(8); 7216 format %{ "FTOSIZS $tmp,$src\n\t" 7217 "FMRS $dst, $tmp" %} 7218 ins_encode %{ 7219 __ ftosizs($tmp$$FloatRegister, $src$$FloatRegister); 7220 __ fmrs($dst$$Register, $tmp$$FloatRegister); 7221 %} 7222 ins_pipe(fcvtF2I); 7223%} 7224 7225// Float to Long conversion 7226instruct convF2L_reg(R0R1RegL dst, regF src, R0RegI arg1) %{ 7227 match(Set dst (ConvF2L src)); 7228 ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME 7229 effect(CALL); 7230 format %{ "convF2L $dst,$src\t! call to SharedRuntime::f2l" %} 7231 ins_encode %{ 7232#ifndef __ABI_HARD__ 7233 __ fmrs($arg1$$Register, $src$$FloatRegister); 7234#else 7235 if($src$$FloatRegister != S0) { 7236 __ mov_float(S0, $src$$FloatRegister); 7237 } 7238#endif 7239 address target = CAST_FROM_FN_PTR(address, SharedRuntime::f2l); 7240 __ call(target, relocInfo::runtime_call_type); 7241 %} 7242 ins_pipe(fcvtF2L); 7243%} 7244 7245instruct convI2D_reg_reg(iRegI src, regD_low dst) %{ 7246 match(Set dst (ConvI2D src)); 7247 ins_cost(DEFAULT_COST + MEMORY_REF_COST); // FIXME 7248 size(8); 7249 format %{ "FMSR $dst,$src \n\t" 7250 "FSITOD $dst $dst"%} 7251 ins_encode %{ 7252 __ fmsr($dst$$FloatRegister, $src$$Register); 7253 __ fsitod($dst$$FloatRegister, $dst$$FloatRegister); 7254 %} 7255 ins_pipe(fcvtI2D); 7256%} 7257 7258instruct convI2F_reg_reg( regF dst, iRegI src ) %{ 7259 match(Set dst (ConvI2F src)); 7260 ins_cost(DEFAULT_COST + MEMORY_REF_COST); // FIXME 7261 size(8); 7262 format %{ "FMSR $dst,$src \n\t" 7263 "FSITOS $dst, $dst"%} 7264 ins_encode %{ 7265 __ fmsr($dst$$FloatRegister, $src$$Register); 7266 __ fsitos($dst$$FloatRegister, $dst$$FloatRegister); 7267 %} 7268 ins_pipe(fcvtI2F); 7269%} 7270 7271instruct convI2L_reg(iRegL dst, iRegI src) %{ 7272 match(Set dst (ConvI2L src)); 7273 size(8); 7274 format %{ "MOV $dst.lo, $src \n\t" 7275 "ASR $dst.hi,$src,31\t! int->long" %} 7276 ins_encode %{ 7277 __ mov($dst$$Register, $src$$Register); 7278 __ mov($dst$$Register->successor(), AsmOperand($src$$Register, asr, 31)); 7279 %} 7280 ins_pipe(ialu_reg_reg); 7281%} 7282 7283// Zero-extend convert int to long 7284instruct convI2L_reg_zex(iRegL dst, iRegI src, immL_32bits mask ) %{ 7285 match(Set dst (AndL (ConvI2L src) mask) ); 7286 size(8); 7287 format %{ "MOV $dst.lo,$src.lo\t! zero-extend int to long\n\t" 7288 "MOV $dst.hi, 0"%} 7289 ins_encode %{ 7290 __ mov($dst$$Register, $src$$Register); 7291 __ mov($dst$$Register->successor(), 0); 7292 %} 7293 ins_pipe(ialu_reg_reg); 7294%} 7295 7296// Zero-extend long 7297instruct zerox_long(iRegL dst, iRegL src, immL_32bits mask ) %{ 7298 match(Set dst (AndL src mask) ); 7299 size(8); 7300 format %{ "MOV $dst.lo,$src.lo\t! zero-extend long\n\t" 7301 "MOV $dst.hi, 0"%} 7302 ins_encode %{ 7303 __ mov($dst$$Register, $src$$Register); 7304 __ mov($dst$$Register->successor(), 0); 7305 %} 7306 ins_pipe(ialu_reg_reg); 7307%} 7308 7309instruct MoveF2I_reg_reg(iRegI dst, regF src) %{ 7310 match(Set dst (MoveF2I src)); 7311 effect(DEF dst, USE src); 7312 ins_cost(MEMORY_REF_COST); // FIXME 7313 7314 size(4); 7315 format %{ "FMRS $dst,$src\t! MoveF2I" %} 7316 ins_encode %{ 7317 __ fmrs($dst$$Register, $src$$FloatRegister); 7318 %} 7319 ins_pipe(iload_mem); // FIXME 7320%} 7321 7322instruct MoveI2F_reg_reg(regF dst, iRegI src) %{ 7323 match(Set dst (MoveI2F src)); 7324 ins_cost(MEMORY_REF_COST); // FIXME 7325 7326 size(4); 7327 format %{ "FMSR $dst,$src\t! MoveI2F" %} 7328 ins_encode %{ 7329 __ fmsr($dst$$FloatRegister, $src$$Register); 7330 %} 7331 ins_pipe(iload_mem); // FIXME 7332%} 7333 7334instruct MoveD2L_reg_reg(iRegL dst, regD src) %{ 7335 match(Set dst (MoveD2L src)); 7336 effect(DEF dst, USE src); 7337 ins_cost(MEMORY_REF_COST); // FIXME 7338 7339 size(4); 7340 format %{ "FMRRD $dst,$src\t! MoveD2L" %} 7341 ins_encode %{ 7342 __ fmrrd($dst$$Register, $dst$$Register->successor(), $src$$FloatRegister); 7343 %} 7344 ins_pipe(iload_mem); // FIXME 7345%} 7346 7347instruct MoveL2D_reg_reg(regD dst, iRegL src) %{ 7348 match(Set dst (MoveL2D src)); 7349 effect(DEF dst, USE src); 7350 ins_cost(MEMORY_REF_COST); // FIXME 7351 7352 size(4); 7353 format %{ "FMDRR $dst,$src\t! MoveL2D" %} 7354 ins_encode %{ 7355 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register->successor()); 7356 %} 7357 ins_pipe(ialu_reg_reg); // FIXME 7358%} 7359 7360//----------- 7361// Long to Double conversion 7362 7363// Magic constant, 0x43300000 7364instruct loadConI_x43300000(iRegI dst) %{ 7365 effect(DEF dst); 7366 size(8); 7367 format %{ "MOV_SLOW $dst,0x43300000\t! 2^52" %} 7368 ins_encode %{ 7369 __ mov_slow($dst$$Register, 0x43300000); 7370 %} 7371 ins_pipe(ialu_none); 7372%} 7373 7374// Magic constant, 0x41f00000 7375instruct loadConI_x41f00000(iRegI dst) %{ 7376 effect(DEF dst); 7377 size(8); 7378 format %{ "MOV_SLOW $dst, 0x41f00000\t! 2^32" %} 7379 ins_encode %{ 7380 __ mov_slow($dst$$Register, 0x41f00000); 7381 %} 7382 ins_pipe(ialu_none); 7383%} 7384 7385instruct loadConI_x0(iRegI dst) %{ 7386 effect(DEF dst); 7387 size(4); 7388 format %{ "MOV $dst, 0x0\t! 0" %} 7389 ins_encode %{ 7390 __ mov($dst$$Register, 0); 7391 %} 7392 ins_pipe(ialu_none); 7393%} 7394 7395// Construct a double from two float halves 7396instruct regDHi_regDLo_to_regD(regD_low dst, regD_low src1, regD_low src2) %{ 7397 effect(DEF dst, USE src1, USE src2); 7398 size(8); 7399 format %{ "FCPYS $dst.hi,$src1.hi\n\t" 7400 "FCPYS $dst.lo,$src2.lo" %} 7401 ins_encode %{ 7402 __ fcpys($dst$$FloatRegister->successor(), $src1$$FloatRegister->successor()); 7403 __ fcpys($dst$$FloatRegister, $src2$$FloatRegister); 7404 %} 7405 ins_pipe(faddD_reg_reg); 7406%} 7407 7408// Convert integer in high half of a double register (in the lower half of 7409// the double register file) to double 7410instruct convI2D_regDHi_regD(regD dst, regD_low src) %{ 7411 effect(DEF dst, USE src); 7412 size(4); 7413 format %{ "FSITOD $dst,$src" %} 7414 ins_encode %{ 7415 __ fsitod($dst$$FloatRegister, $src$$FloatRegister->successor()); 7416 %} 7417 ins_pipe(fcvtLHi2D); 7418%} 7419 7420// Add float double precision 7421instruct addD_regD_regD(regD dst, regD src1, regD src2) %{ 7422 effect(DEF dst, USE src1, USE src2); 7423 size(4); 7424 format %{ "FADDD $dst,$src1,$src2" %} 7425 ins_encode %{ 7426 __ add_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 7427 %} 7428 ins_pipe(faddD_reg_reg); 7429%} 7430 7431// Sub float double precision 7432instruct subD_regD_regD(regD dst, regD src1, regD src2) %{ 7433 effect(DEF dst, USE src1, USE src2); 7434 size(4); 7435 format %{ "FSUBD $dst,$src1,$src2" %} 7436 ins_encode %{ 7437 __ sub_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 7438 %} 7439 ins_pipe(faddD_reg_reg); 7440%} 7441 7442// Mul float double precision 7443instruct mulD_regD_regD(regD dst, regD src1, regD src2) %{ 7444 effect(DEF dst, USE src1, USE src2); 7445 size(4); 7446 format %{ "FMULD $dst,$src1,$src2" %} 7447 ins_encode %{ 7448 __ mul_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 7449 %} 7450 ins_pipe(fmulD_reg_reg); 7451%} 7452 7453instruct regL_to_regD(regD dst, iRegL src) %{ 7454 // No match rule to avoid chain rule match. 7455 effect(DEF dst, USE src); 7456 ins_cost(MEMORY_REF_COST); 7457 size(4); 7458 format %{ "FMDRR $dst,$src\t! regL to regD" %} 7459 ins_encode %{ 7460 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register->successor()); 7461 %} 7462 ins_pipe(ialu_reg_reg); // FIXME 7463%} 7464 7465instruct regI_regI_to_regD(regD dst, iRegI src1, iRegI src2) %{ 7466 // No match rule to avoid chain rule match. 7467 effect(DEF dst, USE src1, USE src2); 7468 ins_cost(MEMORY_REF_COST); 7469 size(4); 7470 format %{ "FMDRR $dst,$src1,$src2\t! regI,regI to regD" %} 7471 ins_encode %{ 7472 __ fmdrr($dst$$FloatRegister, $src1$$Register, $src2$$Register); 7473 %} 7474 ins_pipe(ialu_reg_reg); // FIXME 7475%} 7476 7477instruct convL2D_reg_slow_fxtof(regD dst, iRegL src) %{ 7478 match(Set dst (ConvL2D src)); 7479 ins_cost(DEFAULT_COST*8 + MEMORY_REF_COST*6); // FIXME 7480 7481 expand %{ 7482 regD_low tmpsrc; 7483 iRegI ix43300000; 7484 iRegI ix41f00000; 7485 iRegI ix0; 7486 regD_low dx43300000; 7487 regD dx41f00000; 7488 regD tmp1; 7489 regD_low tmp2; 7490 regD tmp3; 7491 regD tmp4; 7492 7493 regL_to_regD(tmpsrc, src); 7494 7495 loadConI_x43300000(ix43300000); 7496 loadConI_x41f00000(ix41f00000); 7497 loadConI_x0(ix0); 7498 7499 regI_regI_to_regD(dx43300000, ix0, ix43300000); 7500 regI_regI_to_regD(dx41f00000, ix0, ix41f00000); 7501 7502 convI2D_regDHi_regD(tmp1, tmpsrc); 7503 regDHi_regDLo_to_regD(tmp2, dx43300000, tmpsrc); 7504 subD_regD_regD(tmp3, tmp2, dx43300000); 7505 mulD_regD_regD(tmp4, tmp1, dx41f00000); 7506 addD_regD_regD(dst, tmp3, tmp4); 7507 %} 7508%} 7509 7510instruct convL2I_reg(iRegI dst, iRegL src) %{ 7511 match(Set dst (ConvL2I src)); 7512 size(4); 7513 format %{ "MOV $dst,$src.lo\t! long->int" %} 7514 ins_encode %{ 7515 __ mov($dst$$Register, $src$$Register); 7516 %} 7517 ins_pipe(ialu_move_reg_I_to_L); 7518%} 7519 7520// Register Shift Right Immediate 7521instruct shrL_reg_imm6_L2I(iRegI dst, iRegL src, immI_32_63 cnt) %{ 7522 match(Set dst (ConvL2I (RShiftL src cnt))); 7523 size(4); 7524 format %{ "ASR $dst,$src.hi,($cnt - 32)\t! long->int or mov if $cnt==32" %} 7525 ins_encode %{ 7526 if ($cnt$$constant == 32) { 7527 __ mov($dst$$Register, $src$$Register->successor()); 7528 } else { 7529 __ mov($dst$$Register, AsmOperand($src$$Register->successor(), asr, $cnt$$constant - 32)); 7530 } 7531 %} 7532 ins_pipe(ialu_reg_imm); 7533%} 7534 7535 7536//----------Control Flow Instructions------------------------------------------ 7537// Compare Instructions 7538// Compare Integers 7539instruct compI_iReg(flagsReg icc, iRegI op1, iRegI op2) %{ 7540 match(Set icc (CmpI op1 op2)); 7541 effect( DEF icc, USE op1, USE op2 ); 7542 7543 size(4); 7544 format %{ "cmp_32 $op1,$op2\t! int" %} 7545 ins_encode %{ 7546 __ cmp_32($op1$$Register, $op2$$Register); 7547 %} 7548 ins_pipe(ialu_cconly_reg_reg); 7549%} 7550 7551#ifdef _LP64 7552// Compare compressed pointers 7553instruct compN_reg2(flagsRegU icc, iRegN op1, iRegN op2) %{ 7554 match(Set icc (CmpN op1 op2)); 7555 effect( DEF icc, USE op1, USE op2 ); 7556 7557 size(4); 7558 format %{ "cmp_32 $op1,$op2\t! int" %} 7559 ins_encode %{ 7560 __ cmp_32($op1$$Register, $op2$$Register); 7561 %} 7562 ins_pipe(ialu_cconly_reg_reg); 7563%} 7564#endif 7565 7566instruct compU_iReg(flagsRegU icc, iRegI op1, iRegI op2) %{ 7567 match(Set icc (CmpU op1 op2)); 7568 7569 size(4); 7570 format %{ "cmp_32 $op1,$op2\t! unsigned int" %} 7571 ins_encode %{ 7572 __ cmp_32($op1$$Register, $op2$$Register); 7573 %} 7574 ins_pipe(ialu_cconly_reg_reg); 7575%} 7576 7577instruct compI_iReg_immneg(flagsReg icc, iRegI op1, aimmIneg op2) %{ 7578 match(Set icc (CmpI op1 op2)); 7579 effect( DEF icc, USE op1 ); 7580 7581 size(4); 7582 format %{ "cmn_32 $op1,-$op2\t! int" %} 7583 ins_encode %{ 7584 __ cmn_32($op1$$Register, -$op2$$constant); 7585 %} 7586 ins_pipe(ialu_cconly_reg_imm); 7587%} 7588 7589instruct compI_iReg_imm(flagsReg icc, iRegI op1, aimmI op2) %{ 7590 match(Set icc (CmpI op1 op2)); 7591 effect( DEF icc, USE op1 ); 7592 7593 size(4); 7594 format %{ "cmp_32 $op1,$op2\t! int" %} 7595 ins_encode %{ 7596 __ cmp_32($op1$$Register, $op2$$constant); 7597 %} 7598 ins_pipe(ialu_cconly_reg_imm); 7599%} 7600 7601instruct testI_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immI0 zero ) %{ 7602 match(Set icc (CmpI (AndI op1 op2) zero)); 7603 size(4); 7604 format %{ "tst_32 $op2,$op1" %} 7605 7606 ins_encode %{ 7607 __ tst_32($op1$$Register, $op2$$Register); 7608 %} 7609 ins_pipe(ialu_cconly_reg_reg_zero); 7610%} 7611 7612instruct testshlI_reg_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, iRegI op3, immI0 zero ) %{ 7613 match(Set icc (CmpI (AndI op1 (LShiftI op2 op3)) zero)); 7614 size(4); 7615 format %{ "TST $op2,$op1<<$op3" %} 7616 7617 ins_encode %{ 7618 __ tst($op1$$Register, AsmOperand($op2$$Register, lsl, $op3$$Register)); 7619 %} 7620 ins_pipe(ialu_cconly_reg_reg_zero); 7621%} 7622 7623instruct testshlI_reg_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immU5 op3, immI0 zero ) %{ 7624 match(Set icc (CmpI (AndI op1 (LShiftI op2 op3)) zero)); 7625 size(4); 7626 format %{ "tst_32 $op2,$op1<<$op3" %} 7627 7628 ins_encode %{ 7629 __ tst_32($op1$$Register, AsmOperand($op2$$Register, lsl, $op3$$constant)); 7630 %} 7631 ins_pipe(ialu_cconly_reg_reg_zero); 7632%} 7633 7634instruct testsarI_reg_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, iRegI op3, immI0 zero ) %{ 7635 match(Set icc (CmpI (AndI op1 (RShiftI op2 op3)) zero)); 7636 size(4); 7637 format %{ "TST $op2,$op1<<$op3" %} 7638 7639 ins_encode %{ 7640 __ tst($op1$$Register, AsmOperand($op2$$Register, asr, $op3$$Register)); 7641 %} 7642 ins_pipe(ialu_cconly_reg_reg_zero); 7643%} 7644 7645instruct testsarI_reg_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immU5 op3, immI0 zero ) %{ 7646 match(Set icc (CmpI (AndI op1 (RShiftI op2 op3)) zero)); 7647 size(4); 7648 format %{ "tst_32 $op2,$op1<<$op3" %} 7649 7650 ins_encode %{ 7651 __ tst_32($op1$$Register, AsmOperand($op2$$Register, asr, $op3$$constant)); 7652 %} 7653 ins_pipe(ialu_cconly_reg_reg_zero); 7654%} 7655 7656instruct testshrI_reg_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, iRegI op3, immI0 zero ) %{ 7657 match(Set icc (CmpI (AndI op1 (URShiftI op2 op3)) zero)); 7658 size(4); 7659 format %{ "TST $op2,$op1<<$op3" %} 7660 7661 ins_encode %{ 7662 __ tst($op1$$Register, AsmOperand($op2$$Register, lsr, $op3$$Register)); 7663 %} 7664 ins_pipe(ialu_cconly_reg_reg_zero); 7665%} 7666 7667instruct testshrI_reg_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immU5 op3, immI0 zero ) %{ 7668 match(Set icc (CmpI (AndI op1 (URShiftI op2 op3)) zero)); 7669 size(4); 7670 format %{ "tst_32 $op2,$op1<<$op3" %} 7671 7672 ins_encode %{ 7673 __ tst_32($op1$$Register, AsmOperand($op2$$Register, lsr, $op3$$constant)); 7674 %} 7675 ins_pipe(ialu_cconly_reg_reg_zero); 7676%} 7677 7678instruct testI_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, limmI op2, immI0 zero ) %{ 7679 match(Set icc (CmpI (AndI op1 op2) zero)); 7680 size(4); 7681 format %{ "tst_32 $op2,$op1" %} 7682 7683 ins_encode %{ 7684 __ tst_32($op1$$Register, $op2$$constant); 7685 %} 7686 ins_pipe(ialu_cconly_reg_imm_zero); 7687%} 7688 7689instruct compL_reg_reg_LTGE(flagsRegL_LTGE xcc, iRegL op1, iRegL op2, iRegL tmp) %{ 7690 match(Set xcc (CmpL op1 op2)); 7691 effect( DEF xcc, USE op1, USE op2, TEMP tmp ); 7692 7693 size(8); 7694 format %{ "SUBS $tmp,$op1.low,$op2.low\t\t! long\n\t" 7695 "SBCS $tmp,$op1.hi,$op2.hi" %} 7696 ins_encode %{ 7697 __ subs($tmp$$Register, $op1$$Register, $op2$$Register); 7698 __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), $op2$$Register->successor()); 7699 %} 7700 ins_pipe(ialu_cconly_reg_reg); 7701%} 7702 7703instruct compUL_reg_reg_LTGE(flagsRegUL_LTGE xcc, iRegL op1, iRegL op2, iRegL tmp) %{ 7704 match(Set xcc (CmpUL op1 op2)); 7705 effect(DEF xcc, USE op1, USE op2, TEMP tmp); 7706 7707 size(8); 7708 format %{ "SUBS $tmp,$op1.low,$op2.low\t\t! unsigned long\n\t" 7709 "SBCS $tmp,$op1.hi,$op2.hi" %} 7710 ins_encode %{ 7711 __ subs($tmp$$Register, $op1$$Register, $op2$$Register); 7712 __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), $op2$$Register->successor()); 7713 %} 7714 ins_pipe(ialu_cconly_reg_reg); 7715%} 7716 7717instruct compL_reg_reg_EQNE(flagsRegL_EQNE xcc, iRegL op1, iRegL op2) %{ 7718 match(Set xcc (CmpL op1 op2)); 7719 effect( DEF xcc, USE op1, USE op2 ); 7720 7721 size(8); 7722 format %{ "TEQ $op1.hi,$op2.hi\t\t! long\n\t" 7723 "TEQ.eq $op1.lo,$op2.lo" %} 7724 ins_encode %{ 7725 __ teq($op1$$Register->successor(), $op2$$Register->successor()); 7726 __ teq($op1$$Register, $op2$$Register, eq); 7727 %} 7728 ins_pipe(ialu_cconly_reg_reg); 7729%} 7730 7731instruct compL_reg_reg_LEGT(flagsRegL_LEGT xcc, iRegL op1, iRegL op2, iRegL tmp) %{ 7732 match(Set xcc (CmpL op1 op2)); 7733 effect( DEF xcc, USE op1, USE op2, TEMP tmp ); 7734 7735 size(8); 7736 format %{ "SUBS $tmp,$op2.low,$op1.low\t\t! long\n\t" 7737 "SBCS $tmp,$op2.hi,$op1.hi" %} 7738 ins_encode %{ 7739 __ subs($tmp$$Register, $op2$$Register, $op1$$Register); 7740 __ sbcs($tmp$$Register->successor(), $op2$$Register->successor(), $op1$$Register->successor()); 7741 %} 7742 ins_pipe(ialu_cconly_reg_reg); 7743%} 7744 7745// TODO: try immLRot2 instead, (0, $con$$constant) becomes 7746// (hi($con$$constant), lo($con$$constant)) becomes 7747instruct compL_reg_con_LTGE(flagsRegL_LTGE xcc, iRegL op1, immLlowRot con, iRegL tmp) %{ 7748 match(Set xcc (CmpL op1 con)); 7749 effect( DEF xcc, USE op1, USE con, TEMP tmp ); 7750 7751 size(8); 7752 format %{ "SUBS $tmp,$op1.low,$con\t\t! long\n\t" 7753 "SBCS $tmp,$op1.hi,0" %} 7754 ins_encode %{ 7755 __ subs($tmp$$Register, $op1$$Register, $con$$constant); 7756 __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), 0); 7757 %} 7758 7759 ins_pipe(ialu_cconly_reg_reg); 7760%} 7761 7762// TODO: try immLRot2 instead, (0, $con$$constant) becomes 7763// (hi($con$$constant), lo($con$$constant)) becomes 7764instruct compL_reg_con_EQNE(flagsRegL_EQNE xcc, iRegL op1, immLlowRot con) %{ 7765 match(Set xcc (CmpL op1 con)); 7766 effect( DEF xcc, USE op1, USE con ); 7767 7768 size(8); 7769 format %{ "TEQ $op1.hi,0\t\t! long\n\t" 7770 "TEQ.eq $op1.lo,$con" %} 7771 ins_encode %{ 7772 __ teq($op1$$Register->successor(), 0); 7773 __ teq($op1$$Register, $con$$constant, eq); 7774 %} 7775 7776 ins_pipe(ialu_cconly_reg_reg); 7777%} 7778 7779// TODO: try immLRot2 instead, (0, $con$$constant) becomes 7780// (hi($con$$constant), lo($con$$constant)) becomes 7781instruct compL_reg_con_LEGT(flagsRegL_LEGT xcc, iRegL op1, immLlowRot con, iRegL tmp) %{ 7782 match(Set xcc (CmpL op1 con)); 7783 effect( DEF xcc, USE op1, USE con, TEMP tmp ); 7784 7785 size(8); 7786 format %{ "RSBS $tmp,$op1.low,$con\t\t! long\n\t" 7787 "RSCS $tmp,$op1.hi,0" %} 7788 ins_encode %{ 7789 __ rsbs($tmp$$Register, $op1$$Register, $con$$constant); 7790 __ rscs($tmp$$Register->successor(), $op1$$Register->successor(), 0); 7791 %} 7792 7793 ins_pipe(ialu_cconly_reg_reg); 7794%} 7795 7796instruct compUL_reg_reg_EQNE(flagsRegUL_EQNE xcc, iRegL op1, iRegL op2) %{ 7797 match(Set xcc (CmpUL op1 op2)); 7798 effect(DEF xcc, USE op1, USE op2); 7799 7800 size(8); 7801 format %{ "TEQ $op1.hi,$op2.hi\t\t! unsigned long\n\t" 7802 "TEQ.eq $op1.lo,$op2.lo" %} 7803 ins_encode %{ 7804 __ teq($op1$$Register->successor(), $op2$$Register->successor()); 7805 __ teq($op1$$Register, $op2$$Register, eq); 7806 %} 7807 ins_pipe(ialu_cconly_reg_reg); 7808%} 7809 7810instruct compUL_reg_reg_LEGT(flagsRegUL_LEGT xcc, iRegL op1, iRegL op2, iRegL tmp) %{ 7811 match(Set xcc (CmpUL op1 op2)); 7812 effect(DEF xcc, USE op1, USE op2, TEMP tmp); 7813 7814 size(8); 7815 format %{ "SUBS $tmp,$op2.low,$op1.low\t\t! unsigned long\n\t" 7816 "SBCS $tmp,$op2.hi,$op1.hi" %} 7817 ins_encode %{ 7818 __ subs($tmp$$Register, $op2$$Register, $op1$$Register); 7819 __ sbcs($tmp$$Register->successor(), $op2$$Register->successor(), $op1$$Register->successor()); 7820 %} 7821 ins_pipe(ialu_cconly_reg_reg); 7822%} 7823 7824// TODO: try immLRot2 instead, (0, $con$$constant) becomes 7825// (hi($con$$constant), lo($con$$constant)) becomes 7826instruct compUL_reg_con_LTGE(flagsRegUL_LTGE xcc, iRegL op1, immLlowRot con, iRegL tmp) %{ 7827 match(Set xcc (CmpUL op1 con)); 7828 effect(DEF xcc, USE op1, USE con, TEMP tmp); 7829 7830 size(8); 7831 format %{ "SUBS $tmp,$op1.low,$con\t\t! unsigned long\n\t" 7832 "SBCS $tmp,$op1.hi,0" %} 7833 ins_encode %{ 7834 __ subs($tmp$$Register, $op1$$Register, $con$$constant); 7835 __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), 0); 7836 %} 7837 7838 ins_pipe(ialu_cconly_reg_reg); 7839%} 7840 7841// TODO: try immLRot2 instead, (0, $con$$constant) becomes 7842// (hi($con$$constant), lo($con$$constant)) becomes 7843instruct compUL_reg_con_EQNE(flagsRegUL_EQNE xcc, iRegL op1, immLlowRot con) %{ 7844 match(Set xcc (CmpUL op1 con)); 7845 effect(DEF xcc, USE op1, USE con); 7846 7847 size(8); 7848 format %{ "TEQ $op1.hi,0\t\t! unsigned long\n\t" 7849 "TEQ.eq $op1.lo,$con" %} 7850 ins_encode %{ 7851 __ teq($op1$$Register->successor(), 0); 7852 __ teq($op1$$Register, $con$$constant, eq); 7853 %} 7854 7855 ins_pipe(ialu_cconly_reg_reg); 7856%} 7857 7858// TODO: try immLRot2 instead, (0, $con$$constant) becomes 7859// (hi($con$$constant), lo($con$$constant)) becomes 7860instruct compUL_reg_con_LEGT(flagsRegUL_LEGT xcc, iRegL op1, immLlowRot con, iRegL tmp) %{ 7861 match(Set xcc (CmpUL op1 con)); 7862 effect(DEF xcc, USE op1, USE con, TEMP tmp); 7863 7864 size(8); 7865 format %{ "RSBS $tmp,$op1.low,$con\t\t! unsigned long\n\t" 7866 "RSCS $tmp,$op1.hi,0" %} 7867 ins_encode %{ 7868 __ rsbs($tmp$$Register, $op1$$Register, $con$$constant); 7869 __ rscs($tmp$$Register->successor(), $op1$$Register->successor(), 0); 7870 %} 7871 7872 ins_pipe(ialu_cconly_reg_reg); 7873%} 7874 7875/* instruct testL_reg_reg(flagsRegL xcc, iRegL op1, iRegL op2, immL0 zero) %{ */ 7876/* match(Set xcc (CmpL (AndL op1 op2) zero)); */ 7877/* ins_encode %{ */ 7878/* __ stop("testL_reg_reg unimplemented"); */ 7879/* %} */ 7880/* ins_pipe(ialu_cconly_reg_reg); */ 7881/* %} */ 7882 7883/* // useful for checking the alignment of a pointer: */ 7884/* instruct testL_reg_con(flagsRegL xcc, iRegL op1, immLlowRot con, immL0 zero) %{ */ 7885/* match(Set xcc (CmpL (AndL op1 con) zero)); */ 7886/* ins_encode %{ */ 7887/* __ stop("testL_reg_con unimplemented"); */ 7888/* %} */ 7889/* ins_pipe(ialu_cconly_reg_reg); */ 7890/* %} */ 7891 7892instruct compU_iReg_imm(flagsRegU icc, iRegI op1, aimmU31 op2 ) %{ 7893 match(Set icc (CmpU op1 op2)); 7894 7895 size(4); 7896 format %{ "cmp_32 $op1,$op2\t! unsigned" %} 7897 ins_encode %{ 7898 __ cmp_32($op1$$Register, $op2$$constant); 7899 %} 7900 ins_pipe(ialu_cconly_reg_imm); 7901%} 7902 7903// Compare Pointers 7904instruct compP_iRegP(flagsRegP pcc, iRegP op1, iRegP op2 ) %{ 7905 match(Set pcc (CmpP op1 op2)); 7906 7907 size(4); 7908 format %{ "CMP $op1,$op2\t! ptr" %} 7909 ins_encode %{ 7910 __ cmp($op1$$Register, $op2$$Register); 7911 %} 7912 ins_pipe(ialu_cconly_reg_reg); 7913%} 7914 7915instruct compP_iRegP_imm(flagsRegP pcc, iRegP op1, aimmP op2 ) %{ 7916 match(Set pcc (CmpP op1 op2)); 7917 7918 size(4); 7919 format %{ "CMP $op1,$op2\t! ptr" %} 7920 ins_encode %{ 7921 assert($op2$$constant == 0 || _opnds[2]->constant_reloc() == relocInfo::none, "reloc in cmp?"); 7922 __ cmp($op1$$Register, $op2$$constant); 7923 %} 7924 ins_pipe(ialu_cconly_reg_imm); 7925%} 7926 7927//----------Max and Min-------------------------------------------------------- 7928// Min Instructions 7929// Conditional move for min 7930instruct cmovI_reg_lt( iRegI op2, iRegI op1, flagsReg icc ) %{ 7931 effect( USE_DEF op2, USE op1, USE icc ); 7932 7933 size(4); 7934 format %{ "MOV.lt $op2,$op1\t! min" %} 7935 ins_encode %{ 7936 __ mov($op2$$Register, $op1$$Register, lt); 7937 %} 7938 ins_pipe(ialu_reg_flags); 7939%} 7940 7941// Min Register with Register. 7942instruct minI_eReg(iRegI op1, iRegI op2) %{ 7943 match(Set op2 (MinI op1 op2)); 7944 ins_cost(DEFAULT_COST*2); 7945 expand %{ 7946 flagsReg icc; 7947 compI_iReg(icc,op1,op2); 7948 cmovI_reg_lt(op2,op1,icc); 7949 %} 7950%} 7951 7952// Max Instructions 7953// Conditional move for max 7954instruct cmovI_reg_gt( iRegI op2, iRegI op1, flagsReg icc ) %{ 7955 effect( USE_DEF op2, USE op1, USE icc ); 7956 format %{ "MOV.gt $op2,$op1\t! max" %} 7957 ins_encode %{ 7958 __ mov($op2$$Register, $op1$$Register, gt); 7959 %} 7960 ins_pipe(ialu_reg_flags); 7961%} 7962 7963// Max Register with Register 7964instruct maxI_eReg(iRegI op1, iRegI op2) %{ 7965 match(Set op2 (MaxI op1 op2)); 7966 ins_cost(DEFAULT_COST*2); 7967 expand %{ 7968 flagsReg icc; 7969 compI_iReg(icc,op1,op2); 7970 cmovI_reg_gt(op2,op1,icc); 7971 %} 7972%} 7973 7974 7975//----------Float Compares---------------------------------------------------- 7976// Compare floating, generate condition code 7977instruct cmpF_cc(flagsRegF fcc, flagsReg icc, regF src1, regF src2) %{ 7978 match(Set icc (CmpF src1 src2)); 7979 effect(KILL fcc); 7980 7981 size(8); 7982 format %{ "FCMPs $src1,$src2\n\t" 7983 "FMSTAT" %} 7984 ins_encode %{ 7985 __ fcmps($src1$$FloatRegister, $src2$$FloatRegister); 7986 __ fmstat(); 7987 %} 7988 ins_pipe(faddF_fcc_reg_reg_zero); 7989%} 7990 7991instruct cmpF0_cc(flagsRegF fcc, flagsReg icc, regF src1, immF0 src2) %{ 7992 match(Set icc (CmpF src1 src2)); 7993 effect(KILL fcc); 7994 7995 size(8); 7996 format %{ "FCMPs $src1,$src2\n\t" 7997 "FMSTAT" %} 7998 ins_encode %{ 7999 __ fcmpzs($src1$$FloatRegister); 8000 __ fmstat(); 8001 %} 8002 ins_pipe(faddF_fcc_reg_reg_zero); 8003%} 8004 8005instruct cmpD_cc(flagsRegF fcc, flagsReg icc, regD src1, regD src2) %{ 8006 match(Set icc (CmpD src1 src2)); 8007 effect(KILL fcc); 8008 8009 size(8); 8010 format %{ "FCMPd $src1,$src2 \n\t" 8011 "FMSTAT" %} 8012 ins_encode %{ 8013 __ fcmpd($src1$$FloatRegister, $src2$$FloatRegister); 8014 __ fmstat(); 8015 %} 8016 ins_pipe(faddD_fcc_reg_reg_zero); 8017%} 8018 8019instruct cmpD0_cc(flagsRegF fcc, flagsReg icc, regD src1, immD0 src2) %{ 8020 match(Set icc (CmpD src1 src2)); 8021 effect(KILL fcc); 8022 8023 size(8); 8024 format %{ "FCMPZd $src1,$src2 \n\t" 8025 "FMSTAT" %} 8026 ins_encode %{ 8027 __ fcmpzd($src1$$FloatRegister); 8028 __ fmstat(); 8029 %} 8030 ins_pipe(faddD_fcc_reg_reg_zero); 8031%} 8032 8033// Compare floating, generate -1,0,1 8034instruct cmpF_reg(iRegI dst, regF src1, regF src2, flagsRegF fcc) %{ 8035 match(Set dst (CmpF3 src1 src2)); 8036 effect(KILL fcc); 8037 ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME 8038 size(20); 8039 // same number of instructions as code using conditional moves but 8040 // doesn't kill integer condition register 8041 format %{ "FCMPs $dst,$src1,$src2 \n\t" 8042 "VMRS $dst, FPSCR \n\t" 8043 "OR $dst, $dst, 0x08000000 \n\t" 8044 "EOR $dst, $dst, $dst << 3 \n\t" 8045 "MOV $dst, $dst >> 30" %} 8046 ins_encode %{ 8047 __ fcmps($src1$$FloatRegister, $src2$$FloatRegister); 8048 __ floating_cmp($dst$$Register); 8049 %} 8050 ins_pipe( floating_cmp ); 8051%} 8052 8053instruct cmpF0_reg(iRegI dst, regF src1, immF0 src2, flagsRegF fcc) %{ 8054 match(Set dst (CmpF3 src1 src2)); 8055 effect(KILL fcc); 8056 ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME 8057 size(20); 8058 // same number of instructions as code using conditional moves but 8059 // doesn't kill integer condition register 8060 format %{ "FCMPZs $dst,$src1,$src2 \n\t" 8061 "VMRS $dst, FPSCR \n\t" 8062 "OR $dst, $dst, 0x08000000 \n\t" 8063 "EOR $dst, $dst, $dst << 3 \n\t" 8064 "MOV $dst, $dst >> 30" %} 8065 ins_encode %{ 8066 __ fcmpzs($src1$$FloatRegister); 8067 __ floating_cmp($dst$$Register); 8068 %} 8069 ins_pipe( floating_cmp ); 8070%} 8071 8072instruct cmpD_reg(iRegI dst, regD src1, regD src2, flagsRegF fcc) %{ 8073 match(Set dst (CmpD3 src1 src2)); 8074 effect(KILL fcc); 8075 ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME 8076 size(20); 8077 // same number of instructions as code using conditional moves but 8078 // doesn't kill integer condition register 8079 format %{ "FCMPd $dst,$src1,$src2 \n\t" 8080 "VMRS $dst, FPSCR \n\t" 8081 "OR $dst, $dst, 0x08000000 \n\t" 8082 "EOR $dst, $dst, $dst << 3 \n\t" 8083 "MOV $dst, $dst >> 30" %} 8084 ins_encode %{ 8085 __ fcmpd($src1$$FloatRegister, $src2$$FloatRegister); 8086 __ floating_cmp($dst$$Register); 8087 %} 8088 ins_pipe( floating_cmp ); 8089%} 8090 8091instruct cmpD0_reg(iRegI dst, regD src1, immD0 src2, flagsRegF fcc) %{ 8092 match(Set dst (CmpD3 src1 src2)); 8093 effect(KILL fcc); 8094 ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME 8095 size(20); 8096 // same number of instructions as code using conditional moves but 8097 // doesn't kill integer condition register 8098 format %{ "FCMPZd $dst,$src1,$src2 \n\t" 8099 "VMRS $dst, FPSCR \n\t" 8100 "OR $dst, $dst, 0x08000000 \n\t" 8101 "EOR $dst, $dst, $dst << 3 \n\t" 8102 "MOV $dst, $dst >> 30" %} 8103 ins_encode %{ 8104 __ fcmpzd($src1$$FloatRegister); 8105 __ floating_cmp($dst$$Register); 8106 %} 8107 ins_pipe( floating_cmp ); 8108%} 8109 8110//----------Branches--------------------------------------------------------- 8111// Jump 8112// (compare 'operand indIndex' and 'instruct addP_reg_reg' above) 8113// FIXME 8114instruct jumpXtnd(iRegX switch_val, iRegP tmp) %{ 8115 match(Jump switch_val); 8116 effect(TEMP tmp); 8117 ins_cost(350); 8118 format %{ "ADD $tmp, $constanttablebase, $switch_val\n\t" 8119 "LDR $tmp,[$tmp + $constantoffset]\n\t" 8120 "BX $tmp" %} 8121 size(20); 8122 ins_encode %{ 8123 Register table_reg; 8124 Register label_reg = $tmp$$Register; 8125 if (constant_offset() == 0) { 8126 table_reg = $constanttablebase; 8127 __ ldr(label_reg, Address(table_reg, $switch_val$$Register)); 8128 } else { 8129 table_reg = $tmp$$Register; 8130 int offset = $constantoffset; 8131 if (is_memoryP(offset)) { 8132 __ add(table_reg, $constanttablebase, $switch_val$$Register); 8133 __ ldr(label_reg, Address(table_reg, offset)); 8134 } else { 8135 __ mov_slow(table_reg, $constantoffset); 8136 __ add(table_reg, $constanttablebase, table_reg); 8137 __ ldr(label_reg, Address(table_reg, $switch_val$$Register)); 8138 } 8139 } 8140 __ jump(label_reg); // ldr + b better than ldr to PC for branch predictor? 8141 // __ ldr(PC, Address($table$$Register, $switch_val$$Register)); 8142 %} 8143 ins_pipe(ialu_reg_reg); 8144%} 8145 8146// // Direct Branch. 8147instruct branch(label labl) %{ 8148 match(Goto); 8149 effect(USE labl); 8150 8151 size(4); 8152 ins_cost(BRANCH_COST); 8153 format %{ "B $labl" %} 8154 ins_encode %{ 8155 __ b(*($labl$$label)); 8156 %} 8157 ins_pipe(br); 8158%} 8159 8160// Conditional Direct Branch 8161instruct branchCon(cmpOp cmp, flagsReg icc, label labl) %{ 8162 match(If cmp icc); 8163 effect(USE labl); 8164 8165 size(4); 8166 ins_cost(BRANCH_COST); 8167 format %{ "B$cmp $icc,$labl" %} 8168 ins_encode %{ 8169 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 8170 %} 8171 ins_pipe(br_cc); 8172%} 8173 8174#ifdef ARM 8175instruct branchCon_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, label labl) %{ 8176 match(If cmp icc); 8177 effect(USE labl); 8178 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); 8179 8180 size(4); 8181 ins_cost(BRANCH_COST); 8182 format %{ "B$cmp $icc,$labl" %} 8183 ins_encode %{ 8184 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 8185 %} 8186 ins_pipe(br_cc); 8187%} 8188#endif 8189 8190 8191instruct branchConU(cmpOpU cmp, flagsRegU icc, label labl) %{ 8192 match(If cmp icc); 8193 effect(USE labl); 8194 8195 size(4); 8196 ins_cost(BRANCH_COST); 8197 format %{ "B$cmp $icc,$labl" %} 8198 ins_encode %{ 8199 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 8200 %} 8201 ins_pipe(br_cc); 8202%} 8203 8204instruct branchConP(cmpOpP cmp, flagsRegP pcc, label labl) %{ 8205 match(If cmp pcc); 8206 effect(USE labl); 8207 8208 size(4); 8209 ins_cost(BRANCH_COST); 8210 format %{ "B$cmp $pcc,$labl" %} 8211 ins_encode %{ 8212 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 8213 %} 8214 ins_pipe(br_cc); 8215%} 8216 8217instruct branchConL_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, label labl) %{ 8218 match(If cmp xcc); 8219 effect(USE labl); 8220 predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); 8221 8222 size(4); 8223 ins_cost(BRANCH_COST); 8224 format %{ "B$cmp $xcc,$labl" %} 8225 ins_encode %{ 8226 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 8227 %} 8228 ins_pipe(br_cc); 8229%} 8230 8231instruct branchConL_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, label labl) %{ 8232 match(If cmp xcc); 8233 effect(USE labl); 8234 predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); 8235 8236 size(4); 8237 ins_cost(BRANCH_COST); 8238 format %{ "B$cmp $xcc,$labl" %} 8239 ins_encode %{ 8240 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 8241 %} 8242 ins_pipe(br_cc); 8243%} 8244 8245instruct branchConL_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, label labl) %{ 8246 match(If cmp xcc); 8247 effect(USE labl); 8248 predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le ); 8249 8250 size(4); 8251 ins_cost(BRANCH_COST); 8252 format %{ "B$cmp $xcc,$labl" %} 8253 ins_encode %{ 8254 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 8255 %} 8256 ins_pipe(br_cc); 8257%} 8258 8259instruct branchConUL_LTGE(cmpOpUL cmp, flagsRegUL_LTGE xcc, label labl) %{ 8260 match(If cmp xcc); 8261 effect(USE labl); 8262 predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 8263 8264 size(4); 8265 ins_cost(BRANCH_COST); 8266 format %{ "B$cmp $xcc,$labl" %} 8267 ins_encode %{ 8268 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 8269 %} 8270 ins_pipe(br_cc); 8271%} 8272 8273instruct branchConUL_EQNE(cmpOpUL cmp, flagsRegUL_EQNE xcc, label labl) %{ 8274 match(If cmp xcc); 8275 effect(USE labl); 8276 predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne); 8277 8278 size(4); 8279 ins_cost(BRANCH_COST); 8280 format %{ "B$cmp $xcc,$labl" %} 8281 ins_encode %{ 8282 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 8283 %} 8284 ins_pipe(br_cc); 8285%} 8286 8287instruct branchConUL_LEGT(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, label labl) %{ 8288 match(If cmp xcc); 8289 effect(USE labl); 8290 predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le); 8291 8292 size(4); 8293 ins_cost(BRANCH_COST); 8294 format %{ "B$cmp $xcc,$labl" %} 8295 ins_encode %{ 8296 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 8297 %} 8298 ins_pipe(br_cc); 8299%} 8300 8301instruct branchLoopEnd(cmpOp cmp, flagsReg icc, label labl) %{ 8302 match(CountedLoopEnd cmp icc); 8303 effect(USE labl); 8304 8305 size(4); 8306 ins_cost(BRANCH_COST); 8307 format %{ "B$cmp $icc,$labl\t! Loop end" %} 8308 ins_encode %{ 8309 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 8310 %} 8311 ins_pipe(br_cc); 8312%} 8313 8314// instruct branchLoopEndU(cmpOpU cmp, flagsRegU icc, label labl) %{ 8315// match(CountedLoopEnd cmp icc); 8316// ins_pipe(br_cc); 8317// %} 8318 8319// ============================================================================ 8320// Long Compare 8321// 8322// Currently we hold longs in 2 registers. Comparing such values efficiently 8323// is tricky. The flavor of compare used depends on whether we are testing 8324// for LT, LE, or EQ. For a simple LT test we can check just the sign bit. 8325// The GE test is the negated LT test. The LE test can be had by commuting 8326// the operands (yielding a GE test) and then negating; negate again for the 8327// GT test. The EQ test is done by ORcc'ing the high and low halves, and the 8328// NE test is negated from that. 8329 8330// Due to a shortcoming in the ADLC, it mixes up expressions like: 8331// (foo (CmpI (CmpL X Y) 0)) and (bar (CmpI (CmpL X 0L) 0)). Note the 8332// difference between 'Y' and '0L'. The tree-matches for the CmpI sections 8333// are collapsed internally in the ADLC's dfa-gen code. The match for 8334// (CmpI (CmpL X Y) 0) is silently replaced with (CmpI (CmpL X 0L) 0) and the 8335// foo match ends up with the wrong leaf. One fix is to not match both 8336// reg-reg and reg-zero forms of long-compare. This is unfortunate because 8337// both forms beat the trinary form of long-compare and both are very useful 8338// on Intel which has so few registers. 8339 8340// instruct branchCon_long(cmpOp cmp, flagsRegL xcc, label labl) %{ 8341// match(If cmp xcc); 8342// ins_pipe(br_cc); 8343// %} 8344 8345// Manifest a CmpL3 result in an integer register. Very painful. 8346// This is the test to avoid. 8347instruct cmpL3_reg_reg(iRegI dst, iRegL src1, iRegL src2, flagsReg ccr ) %{ 8348 match(Set dst (CmpL3 src1 src2) ); 8349 effect( KILL ccr ); 8350 ins_cost(6*DEFAULT_COST); // FIXME 8351 size(32); 8352 format %{ 8353 "CMP $src1.hi, $src2.hi\t\t! long\n" 8354 "\tMOV.gt $dst, 1\n" 8355 "\tmvn.lt $dst, 0\n" 8356 "\tB.ne done\n" 8357 "\tSUBS $dst, $src1.lo, $src2.lo\n" 8358 "\tMOV.hi $dst, 1\n" 8359 "\tmvn.lo $dst, 0\n" 8360 "done:" %} 8361 ins_encode %{ 8362 Label done; 8363 __ cmp($src1$$Register->successor(), $src2$$Register->successor()); 8364 __ mov($dst$$Register, 1, gt); 8365 __ mvn($dst$$Register, 0, lt); 8366 __ b(done, ne); 8367 __ subs($dst$$Register, $src1$$Register, $src2$$Register); 8368 __ mov($dst$$Register, 1, hi); 8369 __ mvn($dst$$Register, 0, lo); 8370 __ bind(done); 8371 %} 8372 ins_pipe(cmpL_reg); 8373%} 8374 8375// Conditional move 8376instruct cmovLL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegL dst, iRegL src) %{ 8377 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); 8378 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); 8379 8380 ins_cost(150); 8381 size(8); 8382 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t" 8383 "MOV$cmp $dst,$src.hi" %} 8384 ins_encode %{ 8385 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 8386 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode)); 8387 %} 8388 ins_pipe(ialu_reg); 8389%} 8390 8391instruct cmovLL_reg_LTGE_U(cmpOpL cmp, flagsRegUL_LTGE xcc, iRegL dst, iRegL src) %{ 8392 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); 8393 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); 8394 8395 ins_cost(150); 8396 size(8); 8397 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t" 8398 "MOV$cmp $dst,$src.hi" %} 8399 ins_encode %{ 8400 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 8401 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode)); 8402 %} 8403 ins_pipe(ialu_reg); 8404%} 8405 8406instruct cmovLL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegL dst, iRegL src) %{ 8407 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); 8408 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); 8409 8410 ins_cost(150); 8411 size(8); 8412 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t" 8413 "MOV$cmp $dst,$src.hi" %} 8414 ins_encode %{ 8415 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 8416 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode)); 8417 %} 8418 ins_pipe(ialu_reg); 8419%} 8420 8421instruct cmovLL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegL dst, iRegL src) %{ 8422 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); 8423 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); 8424 8425 ins_cost(150); 8426 size(8); 8427 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t" 8428 "MOV$cmp $dst,$src.hi" %} 8429 ins_encode %{ 8430 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 8431 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode)); 8432 %} 8433 ins_pipe(ialu_reg); 8434%} 8435 8436instruct cmovLL_reg_LEGT_U(cmpOpL_commute cmp, flagsRegUL_LEGT xcc, iRegL dst, iRegL src) %{ 8437 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); 8438 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); 8439 8440 ins_cost(150); 8441 size(8); 8442 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t" 8443 "MOV$cmp $dst,$src.hi" %} 8444 ins_encode %{ 8445 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 8446 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode)); 8447 %} 8448 ins_pipe(ialu_reg); 8449%} 8450 8451instruct cmovLL_imm_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegL dst, immL0 src) %{ 8452 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); 8453 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); 8454 ins_cost(140); 8455 size(8); 8456 format %{ "MOV$cmp $dst.lo,0\t! long\n\t" 8457 "MOV$cmp $dst,0" %} 8458 ins_encode %{ 8459 __ mov($dst$$Register, 0, (AsmCondition)($cmp$$cmpcode)); 8460 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 8461 %} 8462 ins_pipe(ialu_imm); 8463%} 8464 8465instruct cmovLL_imm_LTGE_U(cmpOpL cmp, flagsRegUL_LTGE xcc, iRegL dst, immL0 src) %{ 8466 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); 8467 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); 8468 ins_cost(140); 8469 size(8); 8470 format %{ "MOV$cmp $dst.lo,0\t! long\n\t" 8471 "MOV$cmp $dst,0" %} 8472 ins_encode %{ 8473 __ mov($dst$$Register, 0, (AsmCondition)($cmp$$cmpcode)); 8474 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 8475 %} 8476 ins_pipe(ialu_imm); 8477%} 8478 8479instruct cmovLL_imm_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegL dst, immL0 src) %{ 8480 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); 8481 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); 8482 ins_cost(140); 8483 size(8); 8484 format %{ "MOV$cmp $dst.lo,0\t! long\n\t" 8485 "MOV$cmp $dst,0" %} 8486 ins_encode %{ 8487 __ mov($dst$$Register, 0, (AsmCondition)($cmp$$cmpcode)); 8488 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 8489 %} 8490 ins_pipe(ialu_imm); 8491%} 8492 8493instruct cmovLL_imm_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegL dst, immL0 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 ins_cost(140); 8497 size(8); 8498 format %{ "MOV$cmp $dst.lo,0\t! long\n\t" 8499 "MOV$cmp $dst,0" %} 8500 ins_encode %{ 8501 __ mov($dst$$Register, 0, (AsmCondition)($cmp$$cmpcode)); 8502 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 8503 %} 8504 ins_pipe(ialu_imm); 8505%} 8506 8507instruct cmovIL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegI dst, iRegI src) %{ 8508 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 8509 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); 8510 8511 ins_cost(150); 8512 size(4); 8513 format %{ "MOV$cmp $dst,$src" %} 8514 ins_encode %{ 8515 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 8516 %} 8517 ins_pipe(ialu_reg); 8518%} 8519 8520instruct cmovIL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegI dst, iRegI src) %{ 8521 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 8522 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); 8523 8524 ins_cost(150); 8525 size(4); 8526 format %{ "MOV$cmp $dst,$src" %} 8527 ins_encode %{ 8528 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 8529 %} 8530 ins_pipe(ialu_reg); 8531%} 8532 8533instruct cmovIL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegI dst, iRegI src) %{ 8534 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 8535 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); 8536 8537 ins_cost(150); 8538 size(4); 8539 format %{ "MOV$cmp $dst,$src" %} 8540 ins_encode %{ 8541 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 8542 %} 8543 ins_pipe(ialu_reg); 8544%} 8545 8546instruct cmovIL_imm_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegI dst, immI16 src) %{ 8547 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 8548 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); 8549 8550 ins_cost(140); 8551 format %{ "MOVW$cmp $dst,$src" %} 8552 ins_encode %{ 8553 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 8554 %} 8555 ins_pipe(ialu_imm); 8556%} 8557 8558instruct cmovIL_imm_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegI dst, immI16 src) %{ 8559 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 8560 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); 8561 8562 ins_cost(140); 8563 format %{ "MOVW$cmp $dst,$src" %} 8564 ins_encode %{ 8565 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 8566 %} 8567 ins_pipe(ialu_imm); 8568%} 8569 8570instruct cmovIL_imm_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegI dst, immI16 src) %{ 8571 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 8572 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); 8573 8574 ins_cost(140); 8575 format %{ "MOVW$cmp $dst,$src" %} 8576 ins_encode %{ 8577 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 8578 %} 8579 ins_pipe(ialu_imm); 8580%} 8581 8582instruct cmovPL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegP dst, iRegP src) %{ 8583 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); 8584 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); 8585 8586 ins_cost(150); 8587 size(4); 8588 format %{ "MOV$cmp $dst,$src" %} 8589 ins_encode %{ 8590 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 8591 %} 8592 ins_pipe(ialu_reg); 8593%} 8594 8595instruct cmovPL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegP dst, iRegP src) %{ 8596 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); 8597 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); 8598 8599 ins_cost(150); 8600 size(4); 8601 format %{ "MOV$cmp $dst,$src" %} 8602 ins_encode %{ 8603 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 8604 %} 8605 ins_pipe(ialu_reg); 8606%} 8607 8608instruct cmovPL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegP dst, iRegP src) %{ 8609 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); 8610 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); 8611 8612 ins_cost(150); 8613 size(4); 8614 format %{ "MOV$cmp $dst,$src" %} 8615 ins_encode %{ 8616 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 8617 %} 8618 ins_pipe(ialu_reg); 8619%} 8620 8621instruct cmovPL_imm_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegP dst, immP0 src) %{ 8622 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); 8623 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); 8624 8625 ins_cost(140); 8626 format %{ "MOVW$cmp $dst,$src" %} 8627 ins_encode %{ 8628 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 8629 %} 8630 ins_pipe(ialu_imm); 8631%} 8632 8633instruct cmovPL_imm_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegP dst, immP0 src) %{ 8634 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); 8635 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); 8636 8637 ins_cost(140); 8638 format %{ "MOVW$cmp $dst,$src" %} 8639 ins_encode %{ 8640 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 8641 %} 8642 ins_pipe(ialu_imm); 8643%} 8644 8645instruct cmovPL_imm_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegP dst, immP0 src) %{ 8646 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); 8647 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); 8648 8649 ins_cost(140); 8650 format %{ "MOVW$cmp $dst,$src" %} 8651 ins_encode %{ 8652 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 8653 %} 8654 ins_pipe(ialu_imm); 8655%} 8656 8657instruct cmovFL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, regF dst, regF src) %{ 8658 match(Set dst (CMoveF (Binary cmp xcc) (Binary dst src))); 8659 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); 8660 ins_cost(150); 8661 size(4); 8662 format %{ "FCPYS$cmp $dst,$src" %} 8663 ins_encode %{ 8664 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 8665 %} 8666 ins_pipe(int_conditional_float_move); 8667%} 8668 8669instruct cmovFL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, regF dst, regF src) %{ 8670 match(Set dst (CMoveF (Binary cmp xcc) (Binary dst src))); 8671 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); 8672 ins_cost(150); 8673 size(4); 8674 format %{ "FCPYS$cmp $dst,$src" %} 8675 ins_encode %{ 8676 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 8677 %} 8678 ins_pipe(int_conditional_float_move); 8679%} 8680 8681instruct cmovFL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, regF dst, regF src) %{ 8682 match(Set dst (CMoveF (Binary cmp xcc) (Binary dst src))); 8683 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); 8684 ins_cost(150); 8685 size(4); 8686 format %{ "FCPYS$cmp $dst,$src" %} 8687 ins_encode %{ 8688 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 8689 %} 8690 ins_pipe(int_conditional_float_move); 8691%} 8692 8693instruct cmovDL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, regD dst, regD src) %{ 8694 match(Set dst (CMoveD (Binary cmp xcc) (Binary dst src))); 8695 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); 8696 8697 ins_cost(150); 8698 size(4); 8699 format %{ "FCPYD$cmp $dst,$src" %} 8700 ins_encode %{ 8701 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 8702 %} 8703 ins_pipe(int_conditional_float_move); 8704%} 8705 8706instruct cmovDL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, regD dst, regD src) %{ 8707 match(Set dst (CMoveD (Binary cmp xcc) (Binary dst src))); 8708 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); 8709 8710 ins_cost(150); 8711 size(4); 8712 format %{ "FCPYD$cmp $dst,$src" %} 8713 ins_encode %{ 8714 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 8715 %} 8716 ins_pipe(int_conditional_float_move); 8717%} 8718 8719instruct cmovDL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, regD dst, regD src) %{ 8720 match(Set dst (CMoveD (Binary cmp xcc) (Binary dst src))); 8721 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); 8722 8723 ins_cost(150); 8724 size(4); 8725 format %{ "FCPYD$cmp $dst,$src" %} 8726 ins_encode %{ 8727 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 8728 %} 8729 ins_pipe(int_conditional_float_move); 8730%} 8731 8732// ============================================================================ 8733// Safepoint Instruction 8734// rather than KILL R12, it would be better to use any reg as 8735// TEMP. Can't do that at this point because it crashes the compiler 8736instruct safePoint_poll(iRegP poll, R12RegI tmp, flagsReg icc) %{ 8737 match(SafePoint poll); 8738 effect(USE poll, KILL tmp, KILL icc); 8739 8740 size(4); 8741 format %{ "LDR $tmp,[$poll]\t! Safepoint: poll for GC" %} 8742 ins_encode %{ 8743 __ relocate(relocInfo::poll_type); 8744 __ ldr($tmp$$Register, Address($poll$$Register)); 8745 %} 8746 ins_pipe(loadPollP); 8747%} 8748 8749 8750// ============================================================================ 8751// Call Instructions 8752// Call Java Static Instruction 8753instruct CallStaticJavaDirect( method meth ) %{ 8754 match(CallStaticJava); 8755 predicate(! ((CallStaticJavaNode*)n)->is_method_handle_invoke()); 8756 effect(USE meth); 8757 8758 ins_cost(CALL_COST); 8759 format %{ "CALL,static ==> " %} 8760 ins_encode( Java_Static_Call( meth ), call_epilog ); 8761 ins_pipe(simple_call); 8762%} 8763 8764// Call Java Static Instruction (method handle version) 8765instruct CallStaticJavaHandle( method meth ) %{ 8766 match(CallStaticJava); 8767 predicate(((CallStaticJavaNode*)n)->is_method_handle_invoke()); 8768 effect(USE meth); 8769 // FP is saved by all callees (for interpreter stack correction). 8770 // We use it here for a similar purpose, in {preserve,restore}_FP. 8771 8772 ins_cost(CALL_COST); 8773 format %{ "CALL,static/MethodHandle ==> " %} 8774 ins_encode( preserve_SP, Java_Static_Call( meth ), restore_SP, call_epilog ); 8775 ins_pipe(simple_call); 8776%} 8777 8778// Call Java Dynamic Instruction 8779instruct CallDynamicJavaDirect( method meth ) %{ 8780 match(CallDynamicJava); 8781 effect(USE meth); 8782 8783 ins_cost(CALL_COST); 8784 format %{ "MOV_OOP (empty),R_R8\n\t" 8785 "CALL,dynamic ; NOP ==> " %} 8786 ins_encode( Java_Dynamic_Call( meth ), call_epilog ); 8787 ins_pipe(call); 8788%} 8789 8790// Call Runtime Instruction 8791instruct CallRuntimeDirect(method meth) %{ 8792 match(CallRuntime); 8793 effect(USE meth); 8794 ins_cost(CALL_COST); 8795 format %{ "CALL,runtime" %} 8796 ins_encode( Java_To_Runtime( meth ), 8797 call_epilog ); 8798 ins_pipe(simple_call); 8799%} 8800 8801// Call runtime without safepoint - same as CallRuntime 8802instruct CallLeafDirect(method meth) %{ 8803 match(CallLeaf); 8804 effect(USE meth); 8805 ins_cost(CALL_COST); 8806 format %{ "CALL,runtime leaf" %} 8807 // TODO: ned save_last_PC here? 8808 ins_encode( Java_To_Runtime( meth ), 8809 call_epilog ); 8810 ins_pipe(simple_call); 8811%} 8812 8813// Call runtime without safepoint - same as CallLeaf 8814instruct CallLeafNoFPDirect(method meth) %{ 8815 match(CallLeafNoFP); 8816 effect(USE meth); 8817 ins_cost(CALL_COST); 8818 format %{ "CALL,runtime leaf nofp" %} 8819 // TODO: ned save_last_PC here? 8820 ins_encode( Java_To_Runtime( meth ), 8821 call_epilog ); 8822 ins_pipe(simple_call); 8823%} 8824 8825// Tail Call; Jump from runtime stub to Java code. 8826// Also known as an 'interprocedural jump'. 8827// Target of jump will eventually return to caller. 8828// TailJump below removes the return address. 8829instruct TailCalljmpInd(IPRegP jump_target, inline_cache_regP method_ptr) %{ 8830 match(TailCall jump_target method_ptr); 8831 8832 ins_cost(CALL_COST); 8833 format %{ "MOV Rexception_pc, LR\n\t" 8834 "jump $jump_target \t! $method_ptr holds method" %} 8835 ins_encode %{ 8836 __ mov(Rexception_pc, LR); // this is used only to call 8837 // StubRoutines::forward_exception_entry() 8838 // which expects PC of exception in 8839 // R5. FIXME? 8840 __ jump($jump_target$$Register); 8841 %} 8842 ins_pipe(tail_call); 8843%} 8844 8845 8846// Return Instruction 8847instruct Ret() %{ 8848 match(Return); 8849 8850 format %{ "ret LR" %} 8851 8852 ins_encode %{ 8853 __ ret(LR); 8854 %} 8855 8856 ins_pipe(br); 8857%} 8858 8859 8860// Tail Jump; remove the return address; jump to target. 8861// TailCall above leaves the return address around. 8862// TailJump is used in only one place, the rethrow_Java stub (fancy_jump=2). 8863// ex_oop (Exception Oop) is needed in %o0 at the jump. As there would be a 8864// "restore" before this instruction (in Epilogue), we need to materialize it 8865// in %i0. 8866instruct tailjmpInd(IPRegP jump_target, RExceptionRegP ex_oop) %{ 8867 match( TailJump jump_target ex_oop ); 8868 ins_cost(CALL_COST); 8869 format %{ "MOV Rexception_pc, LR\n\t" 8870 "jump $jump_target \t! $ex_oop holds exc. oop" %} 8871 ins_encode %{ 8872 __ mov(Rexception_pc, LR); 8873 __ jump($jump_target$$Register); 8874 %} 8875 ins_pipe(tail_call); 8876%} 8877 8878// Create exception oop: created by stack-crawling runtime code. 8879// Created exception is now available to this handler, and is setup 8880// just prior to jumping to this handler. No code emitted. 8881instruct CreateException( RExceptionRegP ex_oop ) 8882%{ 8883 match(Set ex_oop (CreateEx)); 8884 ins_cost(0); 8885 8886 size(0); 8887 // use the following format syntax 8888 format %{ "! exception oop is in Rexception_obj; no code emitted" %} 8889 ins_encode(); 8890 ins_pipe(empty); 8891%} 8892 8893 8894// Rethrow exception: 8895// The exception oop will come in the first argument position. 8896// Then JUMP (not call) to the rethrow stub code. 8897instruct RethrowException() 8898%{ 8899 match(Rethrow); 8900 ins_cost(CALL_COST); 8901 8902 // use the following format syntax 8903 format %{ "b rethrow_stub" %} 8904 ins_encode %{ 8905 Register scratch = R1_tmp; 8906 assert_different_registers(scratch, c_rarg0, LR); 8907 __ jump(OptoRuntime::rethrow_stub(), relocInfo::runtime_call_type, scratch); 8908 %} 8909 ins_pipe(tail_call); 8910%} 8911 8912 8913// Die now 8914instruct ShouldNotReachHere( ) 8915%{ 8916 match(Halt); 8917 ins_cost(CALL_COST); 8918 8919 // Use the following format syntax 8920 format %{ "ShouldNotReachHere" %} 8921 ins_encode %{ 8922 if (is_reachable()) { 8923 __ stop(_halt_reason); 8924 } 8925 %} 8926 ins_pipe(tail_call); 8927%} 8928 8929// ============================================================================ 8930// The 2nd slow-half of a subtype check. Scan the subklass's 2ndary superklass 8931// array for an instance of the superklass. Set a hidden internal cache on a 8932// hit (cache is checked with exposed code in gen_subtype_check()). Return 8933// not zero for a miss or zero for a hit. The encoding ALSO sets flags. 8934instruct partialSubtypeCheck( R0RegP index, R1RegP sub, R2RegP super, flagsRegP pcc, LRRegP lr ) %{ 8935 match(Set index (PartialSubtypeCheck sub super)); 8936 effect( KILL pcc, KILL lr ); 8937 ins_cost(DEFAULT_COST*10); 8938 format %{ "CALL PartialSubtypeCheck" %} 8939 ins_encode %{ 8940 __ call(StubRoutines::Arm::partial_subtype_check(), relocInfo::runtime_call_type); 8941 %} 8942 ins_pipe(partial_subtype_check_pipe); 8943%} 8944 8945/* instruct partialSubtypeCheck_vs_zero( flagsRegP pcc, o1RegP sub, o2RegP super, immP0 zero, o0RegP idx, o7RegP o7 ) %{ */ 8946/* match(Set pcc (CmpP (PartialSubtypeCheck sub super) zero)); */ 8947/* ins_pipe(partial_subtype_check_pipe); */ 8948/* %} */ 8949 8950 8951// ============================================================================ 8952// inlined locking and unlocking 8953 8954instruct cmpFastLock(flagsRegP pcc, iRegP object, iRegP box, iRegP scratch2, iRegP scratch ) 8955%{ 8956 match(Set pcc (FastLock object box)); 8957 predicate(!(UseBiasedLocking && !UseOptoBiasInlining)); 8958 8959 effect(TEMP scratch, TEMP scratch2); 8960 ins_cost(DEFAULT_COST*3); 8961 8962 format %{ "FASTLOCK $object, $box; KILL $scratch, $scratch2" %} 8963 ins_encode %{ 8964 __ fast_lock($object$$Register, $box$$Register, $scratch$$Register, $scratch2$$Register); 8965 %} 8966 ins_pipe(long_memory_op); 8967%} 8968 8969instruct cmpFastLock_noBiasInline(flagsRegP pcc, iRegP object, iRegP box, iRegP scratch2, 8970 iRegP scratch, iRegP scratch3) %{ 8971 match(Set pcc (FastLock object box)); 8972 predicate(UseBiasedLocking && !UseOptoBiasInlining); 8973 8974 effect(TEMP scratch, TEMP scratch2, TEMP scratch3); 8975 ins_cost(DEFAULT_COST*5); 8976 8977 format %{ "FASTLOCK $object, $box; KILL $scratch, $scratch2, $scratch3" %} 8978 ins_encode %{ 8979 __ fast_lock($object$$Register, $box$$Register, $scratch$$Register, $scratch2$$Register, $scratch3$$Register); 8980 %} 8981 ins_pipe(long_memory_op); 8982%} 8983 8984 8985instruct cmpFastUnlock(flagsRegP pcc, iRegP object, iRegP box, iRegP scratch2, iRegP scratch ) %{ 8986 match(Set pcc (FastUnlock object box)); 8987 effect(TEMP scratch, TEMP scratch2); 8988 ins_cost(100); 8989 8990 format %{ "FASTUNLOCK $object, $box; KILL $scratch, $scratch2" %} 8991 ins_encode %{ 8992 __ fast_unlock($object$$Register, $box$$Register, $scratch$$Register, $scratch2$$Register); 8993 %} 8994 ins_pipe(long_memory_op); 8995%} 8996 8997// Count and Base registers are fixed because the allocator cannot 8998// kill unknown registers. The encodings are generic. 8999instruct clear_array(iRegX cnt, iRegP base, iRegI temp, iRegX zero, Universe dummy, flagsReg cpsr) %{ 9000 match(Set dummy (ClearArray cnt base)); 9001 effect(TEMP temp, TEMP zero, KILL cpsr); 9002 ins_cost(300); 9003 format %{ "MOV $zero,0\n" 9004 " MOV $temp,$cnt\n" 9005 "loop: SUBS $temp,$temp,4\t! Count down a dword of bytes\n" 9006 " STR.ge $zero,[$base+$temp]\t! delay slot" 9007 " B.gt loop\t\t! Clearing loop\n" %} 9008 ins_encode %{ 9009 __ mov($zero$$Register, 0); 9010 __ mov($temp$$Register, $cnt$$Register); 9011 Label(loop); 9012 __ bind(loop); 9013 __ subs($temp$$Register, $temp$$Register, 4); 9014 __ str($zero$$Register, Address($base$$Register, $temp$$Register), ge); 9015 __ b(loop, gt); 9016 %} 9017 ins_pipe(long_memory_op); 9018%} 9019 9020#ifdef XXX 9021// FIXME: Why R0/R1/R2/R3? 9022instruct string_compare(R0RegP str1, R1RegP str2, R2RegI cnt1, R3RegI cnt2, iRegI result, 9023 iRegI tmp1, iRegI tmp2, flagsReg ccr) %{ 9024 predicate(!CompactStrings); 9025 match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); 9026 effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ccr, TEMP tmp1, TEMP tmp2); 9027 ins_cost(300); 9028 format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result // TEMP $tmp1, $tmp2" %} 9029 ins_encode( enc_String_Compare(str1, str2, cnt1, cnt2, result, tmp1, tmp2) ); 9030 9031 ins_pipe(long_memory_op); 9032%} 9033 9034// FIXME: Why R0/R1/R2? 9035instruct string_equals(R0RegP str1, R1RegP str2, R2RegI cnt, iRegI result, iRegI tmp1, iRegI tmp2, 9036 flagsReg ccr) %{ 9037 predicate(!CompactStrings); 9038 match(Set result (StrEquals (Binary str1 str2) cnt)); 9039 effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, TEMP tmp1, TEMP tmp2, TEMP result, KILL ccr); 9040 9041 ins_cost(300); 9042 format %{ "String Equals $str1,$str2,$cnt -> $result // TEMP $tmp1, $tmp2" %} 9043 ins_encode( enc_String_Equals(str1, str2, cnt, result, tmp1, tmp2) ); 9044 ins_pipe(long_memory_op); 9045%} 9046 9047// FIXME: Why R0/R1? 9048instruct array_equals(R0RegP ary1, R1RegP ary2, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI result, 9049 flagsReg ccr) %{ 9050 predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU); 9051 match(Set result (AryEq ary1 ary2)); 9052 effect(USE_KILL ary1, USE_KILL ary2, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP result, KILL ccr); 9053 9054 ins_cost(300); 9055 format %{ "Array Equals $ary1,$ary2 -> $result // TEMP $tmp1,$tmp2,$tmp3" %} 9056 ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, tmp3, result)); 9057 ins_pipe(long_memory_op); 9058%} 9059#endif 9060 9061//---------- Zeros Count Instructions ------------------------------------------ 9062 9063instruct countLeadingZerosI(iRegI dst, iRegI src) %{ 9064 match(Set dst (CountLeadingZerosI src)); 9065 size(4); 9066 format %{ "CLZ_32 $dst,$src" %} 9067 ins_encode %{ 9068 __ clz_32($dst$$Register, $src$$Register); 9069 %} 9070 ins_pipe(ialu_reg); 9071%} 9072 9073instruct countLeadingZerosL(iRegI dst, iRegL src, iRegI tmp, flagsReg ccr) %{ 9074 match(Set dst (CountLeadingZerosL src)); 9075 effect(TEMP tmp, TEMP dst, KILL ccr); 9076 size(16); 9077 format %{ "CLZ $dst,$src.hi\n\t" 9078 "TEQ $dst,32\n\t" 9079 "CLZ.eq $tmp,$src.lo\n\t" 9080 "ADD.eq $dst, $dst, $tmp\n\t" %} 9081 ins_encode %{ 9082 __ clz($dst$$Register, $src$$Register->successor()); 9083 __ teq($dst$$Register, 32); 9084 __ clz($tmp$$Register, $src$$Register, eq); 9085 __ add($dst$$Register, $dst$$Register, $tmp$$Register, eq); 9086 %} 9087 ins_pipe(ialu_reg); 9088%} 9089 9090instruct countTrailingZerosI(iRegI dst, iRegI src, iRegI tmp) %{ 9091 match(Set dst (CountTrailingZerosI src)); 9092 effect(TEMP tmp); 9093 size(8); 9094 format %{ "RBIT_32 $tmp, $src\n\t" 9095 "CLZ_32 $dst,$tmp" %} 9096 ins_encode %{ 9097 __ rbit_32($tmp$$Register, $src$$Register); 9098 __ clz_32($dst$$Register, $tmp$$Register); 9099 %} 9100 ins_pipe(ialu_reg); 9101%} 9102 9103instruct countTrailingZerosL(iRegI dst, iRegL src, iRegI tmp, flagsReg ccr) %{ 9104 match(Set dst (CountTrailingZerosL src)); 9105 effect(TEMP tmp, TEMP dst, KILL ccr); 9106 size(24); 9107 format %{ "RBIT $tmp,$src.lo\n\t" 9108 "CLZ $dst,$tmp\n\t" 9109 "TEQ $dst,32\n\t" 9110 "RBIT $tmp,$src.hi\n\t" 9111 "CLZ.eq $tmp,$tmp\n\t" 9112 "ADD.eq $dst,$dst,$tmp\n\t" %} 9113 ins_encode %{ 9114 __ rbit($tmp$$Register, $src$$Register); 9115 __ clz($dst$$Register, $tmp$$Register); 9116 __ teq($dst$$Register, 32); 9117 __ rbit($tmp$$Register, $src$$Register->successor()); 9118 __ clz($tmp$$Register, $tmp$$Register, eq); 9119 __ add($dst$$Register, $dst$$Register, $tmp$$Register, eq); 9120 %} 9121 ins_pipe(ialu_reg); 9122%} 9123 9124 9125//---------- Population Count Instructions ------------------------------------- 9126 9127instruct popCountI(iRegI dst, iRegI src, regD_low tmp) %{ 9128 predicate(UsePopCountInstruction); 9129 match(Set dst (PopCountI src)); 9130 effect(TEMP tmp); 9131 9132 format %{ "FMSR $tmp,$src\n\t" 9133 "VCNT.8 $tmp,$tmp\n\t" 9134 "VPADDL.U8 $tmp,$tmp\n\t" 9135 "VPADDL.U16 $tmp,$tmp\n\t" 9136 "FMRS $dst,$tmp" %} 9137 size(20); 9138 9139 ins_encode %{ 9140 __ fmsr($tmp$$FloatRegister, $src$$Register); 9141 __ vcnt($tmp$$FloatRegister, $tmp$$FloatRegister); 9142 __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 8, 0); 9143 __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 16, 0); 9144 __ fmrs($dst$$Register, $tmp$$FloatRegister); 9145 %} 9146 ins_pipe(ialu_reg); // FIXME 9147%} 9148 9149// Note: Long.bitCount(long) returns an int. 9150instruct popCountL(iRegI dst, iRegL src, regD_low tmp) %{ 9151 predicate(UsePopCountInstruction); 9152 match(Set dst (PopCountL src)); 9153 effect(TEMP tmp); 9154 9155 format %{ "FMDRR $tmp,$src.lo,$src.hi\n\t" 9156 "VCNT.8 $tmp,$tmp\n\t" 9157 "VPADDL.U8 $tmp,$tmp\n\t" 9158 "VPADDL.U16 $tmp,$tmp\n\t" 9159 "VPADDL.U32 $tmp,$tmp\n\t" 9160 "FMRS $dst,$tmp" %} 9161 9162 size(32); 9163 9164 ins_encode %{ 9165 __ fmdrr($tmp$$FloatRegister, $src$$Register, $src$$Register->successor()); 9166 __ vcnt($tmp$$FloatRegister, $tmp$$FloatRegister); 9167 __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 8, 0); 9168 __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 16, 0); 9169 __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 32, 0); 9170 __ fmrs($dst$$Register, $tmp$$FloatRegister); 9171 %} 9172 ins_pipe(ialu_reg); 9173%} 9174 9175 9176// ============================================================================ 9177//------------Bytes reverse-------------------------------------------------- 9178 9179instruct bytes_reverse_int(iRegI dst, iRegI src) %{ 9180 match(Set dst (ReverseBytesI src)); 9181 9182 size(4); 9183 format %{ "REV32 $dst,$src" %} 9184 ins_encode %{ 9185 __ rev($dst$$Register, $src$$Register); 9186 %} 9187 ins_pipe( iload_mem ); // FIXME 9188%} 9189 9190instruct bytes_reverse_long(iRegL dst, iRegL src) %{ 9191 match(Set dst (ReverseBytesL src)); 9192 effect(TEMP dst); 9193 size(8); 9194 format %{ "REV $dst.lo,$src.lo\n\t" 9195 "REV $dst.hi,$src.hi" %} 9196 ins_encode %{ 9197 __ rev($dst$$Register, $src$$Register->successor()); 9198 __ rev($dst$$Register->successor(), $src$$Register); 9199 %} 9200 ins_pipe( iload_mem ); // FIXME 9201%} 9202 9203instruct bytes_reverse_unsigned_short(iRegI dst, iRegI src) %{ 9204 match(Set dst (ReverseBytesUS src)); 9205 size(4); 9206 format %{ "REV16 $dst,$src" %} 9207 ins_encode %{ 9208 __ rev16($dst$$Register, $src$$Register); 9209 %} 9210 ins_pipe( iload_mem ); // FIXME 9211%} 9212 9213instruct bytes_reverse_short(iRegI dst, iRegI src) %{ 9214 match(Set dst (ReverseBytesS src)); 9215 size(4); 9216 format %{ "REVSH $dst,$src" %} 9217 ins_encode %{ 9218 __ revsh($dst$$Register, $src$$Register); 9219 %} 9220 ins_pipe( iload_mem ); // FIXME 9221%} 9222 9223 9224// ====================VECTOR INSTRUCTIONS===================================== 9225 9226// Load Aligned Packed values into a Double Register 9227instruct loadV8(vecD dst, memoryD mem) %{ 9228 predicate(n->as_LoadVector()->memory_size() == 8); 9229 match(Set dst (LoadVector mem)); 9230 ins_cost(MEMORY_REF_COST); 9231 size(4); 9232 format %{ "FLDD $mem,$dst\t! load vector (8 bytes)" %} 9233 ins_encode %{ 9234 __ ldr_double($dst$$FloatRegister, $mem$$Address); 9235 %} 9236 ins_pipe(floadD_mem); 9237%} 9238 9239// Load Aligned Packed values into a Double Register Pair 9240instruct loadV16(vecX dst, memoryvld mem) %{ 9241 predicate(n->as_LoadVector()->memory_size() == 16); 9242 match(Set dst (LoadVector mem)); 9243 ins_cost(MEMORY_REF_COST); 9244 size(4); 9245 format %{ "VLD1 $mem,$dst.Q\t! load vector (16 bytes)" %} 9246 ins_encode %{ 9247 __ vld1($dst$$FloatRegister, $mem$$Address, MacroAssembler::VELEM_SIZE_16, 128); 9248 %} 9249 ins_pipe(floadD_mem); // FIXME 9250%} 9251 9252// Store Vector in Double register to memory 9253instruct storeV8(memoryD mem, vecD src) %{ 9254 predicate(n->as_StoreVector()->memory_size() == 8); 9255 match(Set mem (StoreVector mem src)); 9256 ins_cost(MEMORY_REF_COST); 9257 size(4); 9258 format %{ "FSTD $src,$mem\t! store vector (8 bytes)" %} 9259 ins_encode %{ 9260 __ str_double($src$$FloatRegister, $mem$$Address); 9261 %} 9262 ins_pipe(fstoreD_mem_reg); 9263%} 9264 9265// Store Vector in Double Register Pair to memory 9266instruct storeV16(memoryvld mem, vecX src) %{ 9267 predicate(n->as_StoreVector()->memory_size() == 16); 9268 match(Set mem (StoreVector mem src)); 9269 ins_cost(MEMORY_REF_COST); 9270 size(4); 9271 format %{ "VST1 $src,$mem\t! store vector (16 bytes)" %} 9272 ins_encode %{ 9273 __ vst1($src$$FloatRegister, $mem$$Address, MacroAssembler::VELEM_SIZE_16, 128); 9274 %} 9275 ins_pipe(fstoreD_mem_reg); // FIXME 9276%} 9277 9278// Replicate scalar to packed byte values in Double register 9279instruct Repl8B_reg(vecD dst, iRegI src, iRegI tmp) %{ 9280 predicate(n->as_Vector()->length() == 8); 9281 match(Set dst (ReplicateB src)); 9282 ins_cost(DEFAULT_COST*4); 9283 effect(TEMP tmp); 9284 size(16); 9285 9286 // FIXME: could use PKH instruction instead? 9287 format %{ "LSL $tmp, $src, 24 \n\t" 9288 "OR $tmp, $tmp, ($tmp >> 8) \n\t" 9289 "OR $tmp, $tmp, ($tmp >> 16) \n\t" 9290 "FMDRR $dst,$tmp,$tmp\t" %} 9291 ins_encode %{ 9292 __ mov($tmp$$Register, AsmOperand($src$$Register, lsl, 24)); 9293 __ orr($tmp$$Register, $tmp$$Register, AsmOperand($tmp$$Register, lsr, 8)); 9294 __ orr($tmp$$Register, $tmp$$Register, AsmOperand($tmp$$Register, lsr, 16)); 9295 __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register); 9296 %} 9297 ins_pipe(ialu_reg); // FIXME 9298%} 9299 9300// Replicate scalar to packed byte values in Double register 9301instruct Repl8B_reg_simd(vecD dst, iRegI src) %{ 9302 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 9303 match(Set dst (ReplicateB src)); 9304 size(4); 9305 9306 format %{ "VDUP.8 $dst,$src\t" %} 9307 ins_encode %{ 9308 bool quad = false; 9309 __ vdupI($dst$$FloatRegister, $src$$Register, 9310 MacroAssembler::VELEM_SIZE_8, quad); 9311 %} 9312 ins_pipe(ialu_reg); // FIXME 9313%} 9314 9315// Replicate scalar to packed byte values in Double register pair 9316instruct Repl16B_reg(vecX dst, iRegI src) %{ 9317 predicate(n->as_Vector()->length_in_bytes() == 16); 9318 match(Set dst (ReplicateB src)); 9319 size(4); 9320 9321 format %{ "VDUP.8 $dst.Q,$src\t" %} 9322 ins_encode %{ 9323 bool quad = true; 9324 __ vdupI($dst$$FloatRegister, $src$$Register, 9325 MacroAssembler::VELEM_SIZE_8, quad); 9326 %} 9327 ins_pipe(ialu_reg); // FIXME 9328%} 9329 9330// Replicate scalar constant to packed byte values in Double register 9331instruct Repl8B_immI(vecD dst, immI src, iRegI tmp) %{ 9332 predicate(n->as_Vector()->length() == 8); 9333 match(Set dst (ReplicateB src)); 9334 ins_cost(DEFAULT_COST*2); 9335 effect(TEMP tmp); 9336 size(12); 9337 9338 format %{ "MOV $tmp, Repl4($src))\n\t" 9339 "FMDRR $dst,$tmp,$tmp\t" %} 9340 ins_encode( LdReplImmI(src, dst, tmp, (4), (1)) ); 9341 ins_pipe(loadConFD); // FIXME 9342%} 9343 9344// Replicate scalar constant to packed byte values in Double register 9345// TODO: support negative constants with MVNI? 9346instruct Repl8B_immU8(vecD dst, immU8 src) %{ 9347 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 9348 match(Set dst (ReplicateB src)); 9349 size(4); 9350 9351 format %{ "VMOV.U8 $dst,$src" %} 9352 ins_encode %{ 9353 bool quad = false; 9354 __ vmovI($dst$$FloatRegister, $src$$constant, 9355 MacroAssembler::VELEM_SIZE_8, quad); 9356 %} 9357 ins_pipe(loadConFD); // FIXME 9358%} 9359 9360// Replicate scalar constant to packed byte values in Double register pair 9361instruct Repl16B_immU8(vecX dst, immU8 src) %{ 9362 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 9363 match(Set dst (ReplicateB src)); 9364 size(4); 9365 9366 format %{ "VMOV.U8 $dst.Q,$src" %} 9367 ins_encode %{ 9368 bool quad = true; 9369 __ vmovI($dst$$FloatRegister, $src$$constant, 9370 MacroAssembler::VELEM_SIZE_8, quad); 9371 %} 9372 ins_pipe(loadConFD); // FIXME 9373%} 9374 9375// Replicate scalar to packed short/char values into Double register 9376instruct Repl4S_reg(vecD dst, iRegI src, iRegI tmp) %{ 9377 predicate(n->as_Vector()->length() == 4); 9378 match(Set dst (ReplicateS src)); 9379 ins_cost(DEFAULT_COST*3); 9380 effect(TEMP tmp); 9381 size(12); 9382 9383 // FIXME: could use PKH instruction instead? 9384 format %{ "LSL $tmp, $src, 16 \n\t" 9385 "OR $tmp, $tmp, ($tmp >> 16) \n\t" 9386 "FMDRR $dst,$tmp,$tmp\t" %} 9387 ins_encode %{ 9388 __ mov($tmp$$Register, AsmOperand($src$$Register, lsl, 16)); 9389 __ orr($tmp$$Register, $tmp$$Register, AsmOperand($tmp$$Register, lsr, 16)); 9390 __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register); 9391 %} 9392 ins_pipe(ialu_reg); // FIXME 9393%} 9394 9395// Replicate scalar to packed byte values in Double register 9396instruct Repl4S_reg_simd(vecD dst, iRegI src) %{ 9397 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 9398 match(Set dst (ReplicateS src)); 9399 size(4); 9400 9401 format %{ "VDUP.16 $dst,$src\t" %} 9402 ins_encode %{ 9403 bool quad = false; 9404 __ vdupI($dst$$FloatRegister, $src$$Register, 9405 MacroAssembler::VELEM_SIZE_16, quad); 9406 %} 9407 ins_pipe(ialu_reg); // FIXME 9408%} 9409 9410// Replicate scalar to packed byte values in Double register pair 9411instruct Repl8S_reg(vecX dst, iRegI src) %{ 9412 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 9413 match(Set dst (ReplicateS src)); 9414 size(4); 9415 9416 format %{ "VDUP.16 $dst.Q,$src\t" %} 9417 ins_encode %{ 9418 bool quad = true; 9419 __ vdupI($dst$$FloatRegister, $src$$Register, 9420 MacroAssembler::VELEM_SIZE_16, quad); 9421 %} 9422 ins_pipe(ialu_reg); // FIXME 9423%} 9424 9425 9426// Replicate scalar constant to packed short/char values in Double register 9427instruct Repl4S_immI(vecD dst, immI src, iRegP tmp) %{ 9428 predicate(n->as_Vector()->length() == 4); 9429 match(Set dst (ReplicateS src)); 9430 effect(TEMP tmp); 9431 size(12); 9432 ins_cost(DEFAULT_COST*4); // FIXME 9433 9434 format %{ "MOV $tmp, Repl2($src))\n\t" 9435 "FMDRR $dst,$tmp,$tmp\t" %} 9436 ins_encode( LdReplImmI(src, dst, tmp, (2), (2)) ); 9437 ins_pipe(loadConFD); // FIXME 9438%} 9439 9440// Replicate scalar constant to packed byte values in Double register 9441instruct Repl4S_immU8(vecD dst, immU8 src) %{ 9442 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 9443 match(Set dst (ReplicateS src)); 9444 size(4); 9445 9446 format %{ "VMOV.U16 $dst,$src" %} 9447 ins_encode %{ 9448 bool quad = false; 9449 __ vmovI($dst$$FloatRegister, $src$$constant, 9450 MacroAssembler::VELEM_SIZE_16, quad); 9451 %} 9452 ins_pipe(loadConFD); // FIXME 9453%} 9454 9455// Replicate scalar constant to packed byte values in Double register pair 9456instruct Repl8S_immU8(vecX dst, immU8 src) %{ 9457 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 9458 match(Set dst (ReplicateS src)); 9459 size(4); 9460 9461 format %{ "VMOV.U16 $dst.Q,$src" %} 9462 ins_encode %{ 9463 bool quad = true; 9464 __ vmovI($dst$$FloatRegister, $src$$constant, 9465 MacroAssembler::VELEM_SIZE_16, quad); 9466 %} 9467 ins_pipe(loadConFD); // FIXME 9468%} 9469 9470// Replicate scalar to packed int values in Double register 9471instruct Repl2I_reg(vecD dst, iRegI src) %{ 9472 predicate(n->as_Vector()->length() == 2); 9473 match(Set dst (ReplicateI src)); 9474 size(4); 9475 9476 format %{ "FMDRR $dst,$src,$src\t" %} 9477 ins_encode %{ 9478 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register); 9479 %} 9480 ins_pipe(ialu_reg); // FIXME 9481%} 9482 9483// Replicate scalar to packed int values in Double register pair 9484instruct Repl4I_reg(vecX dst, iRegI src) %{ 9485 predicate(n->as_Vector()->length() == 4); 9486 match(Set dst (ReplicateI src)); 9487 ins_cost(DEFAULT_COST*2); 9488 size(8); 9489 9490 format %{ "FMDRR $dst.lo,$src,$src\n\t" 9491 "FMDRR $dst.hi,$src,$src" %} 9492 9493 ins_encode %{ 9494 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register); 9495 __ fmdrr($dst$$FloatRegister->successor()->successor(), 9496 $src$$Register, $src$$Register); 9497 %} 9498 ins_pipe(ialu_reg); // FIXME 9499%} 9500 9501// Replicate scalar to packed int values in Double register 9502instruct Repl2I_reg_simd(vecD dst, iRegI src) %{ 9503 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 9504 match(Set dst (ReplicateI src)); 9505 size(4); 9506 9507 format %{ "VDUP.32 $dst.D,$src\t" %} 9508 ins_encode %{ 9509 bool quad = false; 9510 __ vdupI($dst$$FloatRegister, $src$$Register, 9511 MacroAssembler::VELEM_SIZE_32, quad); 9512 %} 9513 ins_pipe(ialu_reg); // FIXME 9514%} 9515 9516// Replicate scalar to packed int values in Double register pair 9517instruct Repl4I_reg_simd(vecX dst, iRegI src) %{ 9518 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 9519 match(Set dst (ReplicateI src)); 9520 size(4); 9521 9522 format %{ "VDUP.32 $dst.Q,$src\t" %} 9523 ins_encode %{ 9524 bool quad = true; 9525 __ vdupI($dst$$FloatRegister, $src$$Register, 9526 MacroAssembler::VELEM_SIZE_32, quad); 9527 %} 9528 ins_pipe(ialu_reg); // FIXME 9529%} 9530 9531 9532// Replicate scalar zero constant to packed int values in Double register 9533instruct Repl2I_immI(vecD dst, immI src, iRegI tmp) %{ 9534 predicate(n->as_Vector()->length() == 2); 9535 match(Set dst (ReplicateI src)); 9536 effect(TEMP tmp); 9537 size(12); 9538 ins_cost(DEFAULT_COST*4); // FIXME 9539 9540 format %{ "MOV $tmp, Repl1($src))\n\t" 9541 "FMDRR $dst,$tmp,$tmp\t" %} 9542 ins_encode( LdReplImmI(src, dst, tmp, (1), (4)) ); 9543 ins_pipe(loadConFD); // FIXME 9544%} 9545 9546// Replicate scalar constant to packed byte values in Double register 9547instruct Repl2I_immU8(vecD dst, immU8 src) %{ 9548 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 9549 match(Set dst (ReplicateI src)); 9550 size(4); 9551 9552 format %{ "VMOV.I32 $dst.D,$src" %} 9553 ins_encode %{ 9554 bool quad = false; 9555 __ vmovI($dst$$FloatRegister, $src$$constant, 9556 MacroAssembler::VELEM_SIZE_32, quad); 9557 %} 9558 ins_pipe(loadConFD); // FIXME 9559%} 9560 9561// Replicate scalar constant to packed byte values in Double register pair 9562instruct Repl4I_immU8(vecX dst, immU8 src) %{ 9563 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 9564 match(Set dst (ReplicateI src)); 9565 size(4); 9566 9567 format %{ "VMOV.I32 $dst.Q,$src" %} 9568 ins_encode %{ 9569 bool quad = true; 9570 __ vmovI($dst$$FloatRegister, $src$$constant, 9571 MacroAssembler::VELEM_SIZE_32, quad); 9572 %} 9573 ins_pipe(loadConFD); // FIXME 9574%} 9575 9576// Replicate scalar to packed byte values in Double register pair 9577instruct Repl2L_reg(vecX dst, iRegL src) %{ 9578 predicate(n->as_Vector()->length() == 2); 9579 match(Set dst (ReplicateL src)); 9580 size(8); 9581 ins_cost(DEFAULT_COST*2); // FIXME 9582 9583 format %{ "FMDRR $dst.D,$src.lo,$src.hi\t\n" 9584 "FMDRR $dst.D.next,$src.lo,$src.hi" %} 9585 ins_encode %{ 9586 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register->successor()); 9587 __ fmdrr($dst$$FloatRegister->successor()->successor(), 9588 $src$$Register, $src$$Register->successor()); 9589 %} 9590 ins_pipe(ialu_reg); // FIXME 9591%} 9592 9593 9594// Replicate scalar to packed float values in Double register 9595instruct Repl2F_regI(vecD dst, iRegI src) %{ 9596 predicate(n->as_Vector()->length() == 2); 9597 match(Set dst (ReplicateF src)); 9598 size(4); 9599 9600 format %{ "FMDRR $dst.D,$src,$src\t" %} 9601 ins_encode %{ 9602 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register); 9603 %} 9604 ins_pipe(ialu_reg); // FIXME 9605%} 9606 9607// Replicate scalar to packed float values in Double register 9608instruct Repl2F_reg_vfp(vecD dst, regF src) %{ 9609 predicate(n->as_Vector()->length() == 2); 9610 match(Set dst (ReplicateF src)); 9611 size(4*2); 9612 ins_cost(DEFAULT_COST*2); // FIXME 9613 9614 expand %{ 9615 iRegI tmp; 9616 MoveF2I_reg_reg(tmp, src); 9617 Repl2F_regI(dst,tmp); 9618 %} 9619%} 9620 9621// Replicate scalar to packed float values in Double register 9622instruct Repl2F_reg_simd(vecD dst, regF src) %{ 9623 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 9624 match(Set dst (ReplicateF src)); 9625 size(4); 9626 ins_cost(DEFAULT_COST); // FIXME 9627 9628 format %{ "VDUP.32 $dst.D,$src.D\t" %} 9629 ins_encode %{ 9630 bool quad = false; 9631 __ vdupF($dst$$FloatRegister, $src$$FloatRegister, quad); 9632 %} 9633 ins_pipe(ialu_reg); // FIXME 9634%} 9635 9636// Replicate scalar to packed float values in Double register pair 9637instruct Repl4F_reg(vecX dst, regF src, iRegI tmp) %{ 9638 predicate(n->as_Vector()->length() == 4); 9639 match(Set dst (ReplicateF src)); 9640 effect(TEMP tmp); 9641 size(4*3); 9642 ins_cost(DEFAULT_COST*3); // FIXME 9643 9644 format %{ "FMRS $tmp,$src\n\t" 9645 "FMDRR $dst.D,$tmp,$tmp\n\t" 9646 "FMDRR $dst.D.next,$tmp,$tmp\t" %} 9647 ins_encode %{ 9648 __ fmrs($tmp$$Register, $src$$FloatRegister); 9649 __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register); 9650 __ fmdrr($dst$$FloatRegister->successor()->successor(), 9651 $tmp$$Register, $tmp$$Register); 9652 %} 9653 ins_pipe(ialu_reg); // FIXME 9654%} 9655 9656// Replicate scalar to packed float values in Double register pair 9657instruct Repl4F_reg_simd(vecX dst, regF src) %{ 9658 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 9659 match(Set dst (ReplicateF src)); 9660 size(4); 9661 ins_cost(DEFAULT_COST); // FIXME 9662 9663 format %{ "VDUP.32 $dst.Q,$src.D\t" %} 9664 ins_encode %{ 9665 bool quad = true; 9666 __ vdupF($dst$$FloatRegister, $src$$FloatRegister, quad); 9667 %} 9668 ins_pipe(ialu_reg); // FIXME 9669%} 9670 9671// Replicate scalar zero constant to packed float values in Double register 9672instruct Repl2F_immI(vecD dst, immF src, iRegI tmp) %{ 9673 predicate(n->as_Vector()->length() == 2); 9674 match(Set dst (ReplicateF src)); 9675 effect(TEMP tmp); 9676 size(12); 9677 ins_cost(DEFAULT_COST*4); // FIXME 9678 9679 format %{ "MOV $tmp, Repl1($src))\n\t" 9680 "FMDRR $dst,$tmp,$tmp\t" %} 9681 ins_encode( LdReplImmF(src, dst, tmp) ); 9682 ins_pipe(loadConFD); // FIXME 9683%} 9684 9685// Replicate scalar to packed double float values in Double register pair 9686instruct Repl2D_reg(vecX dst, regD src) %{ 9687 predicate(n->as_Vector()->length() == 2); 9688 match(Set dst (ReplicateD src)); 9689 size(4*2); 9690 ins_cost(DEFAULT_COST*2); // FIXME 9691 9692 format %{ "FCPYD $dst.D.a,$src\n\t" 9693 "FCPYD $dst.D.b,$src\t" %} 9694 ins_encode %{ 9695 FloatRegister dsta = $dst$$FloatRegister; 9696 FloatRegister src = $src$$FloatRegister; 9697 __ fcpyd(dsta, src); 9698 FloatRegister dstb = dsta->successor()->successor(); 9699 __ fcpyd(dstb, src); 9700 %} 9701 ins_pipe(ialu_reg); // FIXME 9702%} 9703 9704// ====================VECTOR ARITHMETIC======================================= 9705 9706// --------------------------------- ADD -------------------------------------- 9707 9708// Bytes vector add 9709instruct vadd8B_reg(vecD dst, vecD src1, vecD src2) %{ 9710 predicate(n->as_Vector()->length() == 8); 9711 match(Set dst (AddVB src1 src2)); 9712 format %{ "VADD.I8 $dst,$src1,$src2\t! add packed8B" %} 9713 size(4); 9714 ins_encode %{ 9715 bool quad = false; 9716 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 9717 MacroAssembler::VELEM_SIZE_8, quad); 9718 %} 9719 ins_pipe( ialu_reg_reg ); // FIXME 9720%} 9721 9722instruct vadd16B_reg(vecX dst, vecX src1, vecX src2) %{ 9723 predicate(n->as_Vector()->length() == 16); 9724 match(Set dst (AddVB src1 src2)); 9725 size(4); 9726 format %{ "VADD.I8 $dst.Q,$src1.Q,$src2.Q\t! add packed16B" %} 9727 ins_encode %{ 9728 bool quad = true; 9729 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 9730 MacroAssembler::VELEM_SIZE_8, quad); 9731 %} 9732 ins_pipe( ialu_reg_reg ); // FIXME 9733%} 9734 9735// Shorts/Chars vector add 9736instruct vadd4S_reg(vecD dst, vecD src1, vecD src2) %{ 9737 predicate(n->as_Vector()->length() == 4); 9738 match(Set dst (AddVS src1 src2)); 9739 size(4); 9740 format %{ "VADD.I16 $dst,$src1,$src2\t! add packed4S" %} 9741 ins_encode %{ 9742 bool quad = false; 9743 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 9744 MacroAssembler::VELEM_SIZE_16, quad); 9745 %} 9746 ins_pipe( ialu_reg_reg ); // FIXME 9747%} 9748 9749instruct vadd8S_reg(vecX dst, vecX src1, vecX src2) %{ 9750 predicate(n->as_Vector()->length() == 8); 9751 match(Set dst (AddVS src1 src2)); 9752 size(4); 9753 format %{ "VADD.I16 $dst.Q,$src1.Q,$src2.Q\t! add packed8S" %} 9754 ins_encode %{ 9755 bool quad = true; 9756 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 9757 MacroAssembler::VELEM_SIZE_16, quad); 9758 %} 9759 ins_pipe( ialu_reg_reg ); // FIXME 9760%} 9761 9762// Integers vector add 9763instruct vadd2I_reg(vecD dst, vecD src1, vecD src2) %{ 9764 predicate(n->as_Vector()->length() == 2); 9765 match(Set dst (AddVI src1 src2)); 9766 size(4); 9767 format %{ "VADD.I32 $dst.D,$src1.D,$src2.D\t! add packed2I" %} 9768 ins_encode %{ 9769 bool quad = false; 9770 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 9771 MacroAssembler::VELEM_SIZE_32, quad); 9772 %} 9773 ins_pipe( ialu_reg_reg ); // FIXME 9774%} 9775 9776instruct vadd4I_reg(vecX dst, vecX src1, vecX src2) %{ 9777 predicate(n->as_Vector()->length() == 4); 9778 match(Set dst (AddVI src1 src2)); 9779 size(4); 9780 format %{ "VADD.I32 $dst.Q,$src1.Q,$src2.Q\t! add packed4I" %} 9781 ins_encode %{ 9782 bool quad = true; 9783 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 9784 MacroAssembler::VELEM_SIZE_32, quad); 9785 %} 9786 ins_pipe( ialu_reg_reg ); // FIXME 9787%} 9788 9789// Longs vector add 9790instruct vadd2L_reg(vecX dst, vecX src1, vecX src2) %{ 9791 predicate(n->as_Vector()->length() == 2); 9792 match(Set dst (AddVL src1 src2)); 9793 size(4); 9794 format %{ "VADD.I64 $dst.Q,$src1.Q,$src2.Q\t! add packed2L" %} 9795 ins_encode %{ 9796 bool quad = true; 9797 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 9798 MacroAssembler::VELEM_SIZE_64, quad); 9799 %} 9800 ins_pipe( ialu_reg_reg ); // FIXME 9801%} 9802 9803// Floats vector add 9804instruct vadd2F_reg(vecD dst, vecD src1, vecD src2) %{ 9805 predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant()); 9806 match(Set dst (AddVF src1 src2)); 9807 size(4); 9808 format %{ "VADD.F32 $dst,$src1,$src2\t! add packed2F" %} 9809 ins_encode %{ 9810 bool quad = false; 9811 __ vaddF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 9812 MacroAssembler::VFA_SIZE_F32, quad); 9813 %} 9814 ins_pipe( faddD_reg_reg ); // FIXME 9815%} 9816 9817instruct vadd2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{ 9818 predicate(n->as_Vector()->length() == 2 && !VM_Version::simd_math_is_compliant()); 9819 match(Set dst (AddVF src1 src2)); 9820 ins_cost(DEFAULT_COST*2); // FIXME 9821 9822 size(4*2); 9823 format %{ "FADDS $dst.a,$src1.a,$src2.a\n\t" 9824 "FADDS $dst.b,$src1.b,$src2.b" %} 9825 ins_encode %{ 9826 __ add_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 9827 __ add_float($dst$$FloatRegister->successor(), 9828 $src1$$FloatRegister->successor(), 9829 $src2$$FloatRegister->successor()); 9830 %} 9831 9832 ins_pipe(faddF_reg_reg); // FIXME 9833%} 9834 9835instruct vadd4F_reg_simd(vecX dst, vecX src1, vecX src2) %{ 9836 predicate(n->as_Vector()->length() == 4 && VM_Version::simd_math_is_compliant()); 9837 match(Set dst (AddVF src1 src2)); 9838 size(4); 9839 format %{ "VADD.F32 $dst.Q,$src1.Q,$src2.Q\t! add packed4F" %} 9840 ins_encode %{ 9841 bool quad = true; 9842 __ vaddF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 9843 MacroAssembler::VFA_SIZE_F32, quad); 9844 %} 9845 ins_pipe( faddD_reg_reg ); // FIXME 9846%} 9847 9848instruct vadd4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 9849 predicate(n->as_Vector()->length() == 4 && !VM_Version::simd_math_is_compliant()); 9850 match(Set dst (AddVF src1 src2)); 9851 size(4*4); 9852 ins_cost(DEFAULT_COST*4); // FIXME 9853 9854 format %{ "FADDS $dst.a,$src1.a,$src2.a\n\t" 9855 "FADDS $dst.b,$src1.b,$src2.b\n\t" 9856 "FADDS $dst.c,$src1.c,$src2.c\n\t" 9857 "FADDS $dst.d,$src1.d,$src2.d" %} 9858 9859 ins_encode %{ 9860 FloatRegister dsta = $dst$$FloatRegister; 9861 FloatRegister src1a = $src1$$FloatRegister; 9862 FloatRegister src2a = $src2$$FloatRegister; 9863 __ add_float(dsta, src1a, src2a); 9864 FloatRegister dstb = dsta->successor(); 9865 FloatRegister src1b = src1a->successor(); 9866 FloatRegister src2b = src2a->successor(); 9867 __ add_float(dstb, src1b, src2b); 9868 FloatRegister dstc = dstb->successor(); 9869 FloatRegister src1c = src1b->successor(); 9870 FloatRegister src2c = src2b->successor(); 9871 __ add_float(dstc, src1c, src2c); 9872 FloatRegister dstd = dstc->successor(); 9873 FloatRegister src1d = src1c->successor(); 9874 FloatRegister src2d = src2c->successor(); 9875 __ add_float(dstd, src1d, src2d); 9876 %} 9877 9878 ins_pipe(faddF_reg_reg); // FIXME 9879%} 9880 9881instruct vadd2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 9882 predicate(n->as_Vector()->length() == 2); 9883 match(Set dst (AddVD src1 src2)); 9884 size(4*2); 9885 ins_cost(DEFAULT_COST*2); // FIXME 9886 9887 format %{ "FADDD $dst.a,$src1.a,$src2.a\n\t" 9888 "FADDD $dst.b,$src1.b,$src2.b" %} 9889 9890 ins_encode %{ 9891 FloatRegister dsta = $dst$$FloatRegister; 9892 FloatRegister src1a = $src1$$FloatRegister; 9893 FloatRegister src2a = $src2$$FloatRegister; 9894 __ add_double(dsta, src1a, src2a); 9895 FloatRegister dstb = dsta->successor()->successor(); 9896 FloatRegister src1b = src1a->successor()->successor(); 9897 FloatRegister src2b = src2a->successor()->successor(); 9898 __ add_double(dstb, src1b, src2b); 9899 %} 9900 9901 ins_pipe(faddF_reg_reg); // FIXME 9902%} 9903 9904 9905// Bytes vector sub 9906instruct vsub8B_reg(vecD dst, vecD src1, vecD src2) %{ 9907 predicate(n->as_Vector()->length() == 8); 9908 match(Set dst (SubVB src1 src2)); 9909 size(4); 9910 format %{ "VSUB.I8 $dst,$src1,$src2\t! sub packed8B" %} 9911 ins_encode %{ 9912 bool quad = false; 9913 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 9914 MacroAssembler::VELEM_SIZE_8, quad); 9915 %} 9916 ins_pipe( ialu_reg_reg ); // FIXME 9917%} 9918 9919instruct vsub16B_reg(vecX dst, vecX src1, vecX src2) %{ 9920 predicate(n->as_Vector()->length() == 16); 9921 match(Set dst (SubVB src1 src2)); 9922 size(4); 9923 format %{ "VSUB.I8 $dst.Q,$src1.Q,$src2.Q\t! sub packed16B" %} 9924 ins_encode %{ 9925 bool quad = true; 9926 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 9927 MacroAssembler::VELEM_SIZE_8, quad); 9928 %} 9929 ins_pipe( ialu_reg_reg ); // FIXME 9930%} 9931 9932// Shorts/Chars vector sub 9933instruct vsub4S_reg(vecD dst, vecD src1, vecD src2) %{ 9934 predicate(n->as_Vector()->length() == 4); 9935 match(Set dst (SubVS src1 src2)); 9936 size(4); 9937 format %{ "VSUB.I16 $dst,$src1,$src2\t! sub packed4S" %} 9938 ins_encode %{ 9939 bool quad = false; 9940 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 9941 MacroAssembler::VELEM_SIZE_16, quad); 9942 %} 9943 ins_pipe( ialu_reg_reg ); // FIXME 9944%} 9945 9946instruct vsub16S_reg(vecX dst, vecX src1, vecX src2) %{ 9947 predicate(n->as_Vector()->length() == 8); 9948 match(Set dst (SubVS src1 src2)); 9949 size(4); 9950 format %{ "VSUB.I16 $dst.Q,$src1.Q,$src2.Q\t! sub packed8S" %} 9951 ins_encode %{ 9952 bool quad = true; 9953 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 9954 MacroAssembler::VELEM_SIZE_16, quad); 9955 %} 9956 ins_pipe( ialu_reg_reg ); // FIXME 9957%} 9958 9959// Integers vector sub 9960instruct vsub2I_reg(vecD dst, vecD src1, vecD src2) %{ 9961 predicate(n->as_Vector()->length() == 2); 9962 match(Set dst (SubVI src1 src2)); 9963 size(4); 9964 format %{ "VSUB.I32 $dst,$src1,$src2\t! sub packed2I" %} 9965 ins_encode %{ 9966 bool quad = false; 9967 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 9968 MacroAssembler::VELEM_SIZE_32, quad); 9969 %} 9970 ins_pipe( ialu_reg_reg ); // FIXME 9971%} 9972 9973instruct vsub4I_reg(vecX dst, vecX src1, vecX src2) %{ 9974 predicate(n->as_Vector()->length() == 4); 9975 match(Set dst (SubVI src1 src2)); 9976 size(4); 9977 format %{ "VSUB.I32 $dst.Q,$src1.Q,$src2.Q\t! sub packed4I" %} 9978 ins_encode %{ 9979 bool quad = true; 9980 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 9981 MacroAssembler::VELEM_SIZE_32, quad); 9982 %} 9983 ins_pipe( ialu_reg_reg ); // FIXME 9984%} 9985 9986// Longs vector sub 9987instruct vsub2L_reg(vecX dst, vecX src1, vecX src2) %{ 9988 predicate(n->as_Vector()->length() == 2); 9989 match(Set dst (SubVL src1 src2)); 9990 size(4); 9991 format %{ "VSUB.I64 $dst.Q,$src1.Q,$src2.Q\t! sub packed2L" %} 9992 ins_encode %{ 9993 bool quad = true; 9994 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 9995 MacroAssembler::VELEM_SIZE_64, quad); 9996 %} 9997 ins_pipe( ialu_reg_reg ); // FIXME 9998%} 9999 10000// Floats vector sub 10001instruct vsub2F_reg(vecD dst, vecD src1, vecD src2) %{ 10002 predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant()); 10003 match(Set dst (SubVF src1 src2)); 10004 size(4); 10005 format %{ "VSUB.F32 $dst,$src1,$src2\t! sub packed2F" %} 10006 ins_encode %{ 10007 bool quad = false; 10008 __ vsubF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 10009 MacroAssembler::VFA_SIZE_F32, quad); 10010 %} 10011 ins_pipe( faddF_reg_reg ); // FIXME 10012%} 10013 10014instruct vsub2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{ 10015 predicate(n->as_Vector()->length() == 2 && !VM_Version::simd_math_is_compliant()); 10016 match(Set dst (SubVF src1 src2)); 10017 size(4*2); 10018 ins_cost(DEFAULT_COST*2); // FIXME 10019 10020 format %{ "FSUBS $dst.a,$src1.a,$src2.a\n\t" 10021 "FSUBS $dst.b,$src1.b,$src2.b" %} 10022 10023 ins_encode %{ 10024 FloatRegister dsta = $dst$$FloatRegister; 10025 FloatRegister src1a = $src1$$FloatRegister; 10026 FloatRegister src2a = $src2$$FloatRegister; 10027 __ sub_float(dsta, src1a, src2a); 10028 FloatRegister dstb = dsta->successor(); 10029 FloatRegister src1b = src1a->successor(); 10030 FloatRegister src2b = src2a->successor(); 10031 __ sub_float(dstb, src1b, src2b); 10032 %} 10033 10034 ins_pipe(faddF_reg_reg); // FIXME 10035%} 10036 10037 10038instruct vsub4F_reg(vecX dst, vecX src1, vecX src2) %{ 10039 predicate(n->as_Vector()->length() == 4 && VM_Version::simd_math_is_compliant()); 10040 match(Set dst (SubVF src1 src2)); 10041 size(4); 10042 format %{ "VSUB.F32 $dst.Q,$src1.Q,$src2.Q\t! sub packed4F" %} 10043 ins_encode %{ 10044 bool quad = true; 10045 __ vsubF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 10046 MacroAssembler::VFA_SIZE_F32, quad); 10047 %} 10048 ins_pipe( faddF_reg_reg ); // FIXME 10049%} 10050 10051instruct vsub4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 10052 predicate(n->as_Vector()->length() == 4 && !VM_Version::simd_math_is_compliant()); 10053 match(Set dst (SubVF src1 src2)); 10054 size(4*4); 10055 ins_cost(DEFAULT_COST*4); // FIXME 10056 10057 format %{ "FSUBS $dst.a,$src1.a,$src2.a\n\t" 10058 "FSUBS $dst.b,$src1.b,$src2.b\n\t" 10059 "FSUBS $dst.c,$src1.c,$src2.c\n\t" 10060 "FSUBS $dst.d,$src1.d,$src2.d" %} 10061 10062 ins_encode %{ 10063 FloatRegister dsta = $dst$$FloatRegister; 10064 FloatRegister src1a = $src1$$FloatRegister; 10065 FloatRegister src2a = $src2$$FloatRegister; 10066 __ sub_float(dsta, src1a, src2a); 10067 FloatRegister dstb = dsta->successor(); 10068 FloatRegister src1b = src1a->successor(); 10069 FloatRegister src2b = src2a->successor(); 10070 __ sub_float(dstb, src1b, src2b); 10071 FloatRegister dstc = dstb->successor(); 10072 FloatRegister src1c = src1b->successor(); 10073 FloatRegister src2c = src2b->successor(); 10074 __ sub_float(dstc, src1c, src2c); 10075 FloatRegister dstd = dstc->successor(); 10076 FloatRegister src1d = src1c->successor(); 10077 FloatRegister src2d = src2c->successor(); 10078 __ sub_float(dstd, src1d, src2d); 10079 %} 10080 10081 ins_pipe(faddF_reg_reg); // FIXME 10082%} 10083 10084instruct vsub2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 10085 predicate(n->as_Vector()->length() == 2); 10086 match(Set dst (SubVD src1 src2)); 10087 size(4*2); 10088 ins_cost(DEFAULT_COST*2); // FIXME 10089 10090 format %{ "FSUBD $dst.a,$src1.a,$src2.a\n\t" 10091 "FSUBD $dst.b,$src1.b,$src2.b" %} 10092 10093 ins_encode %{ 10094 FloatRegister dsta = $dst$$FloatRegister; 10095 FloatRegister src1a = $src1$$FloatRegister; 10096 FloatRegister src2a = $src2$$FloatRegister; 10097 __ sub_double(dsta, src1a, src2a); 10098 FloatRegister dstb = dsta->successor()->successor(); 10099 FloatRegister src1b = src1a->successor()->successor(); 10100 FloatRegister src2b = src2a->successor()->successor(); 10101 __ sub_double(dstb, src1b, src2b); 10102 %} 10103 10104 ins_pipe(faddF_reg_reg); // FIXME 10105%} 10106 10107// Shorts/Chars vector mul 10108instruct vmul4S_reg(vecD dst, vecD src1, vecD src2) %{ 10109 predicate(n->as_Vector()->length() == 4); 10110 match(Set dst (MulVS src1 src2)); 10111 size(4); 10112 format %{ "VMUL.I16 $dst,$src1,$src2\t! mul packed4S" %} 10113 ins_encode %{ 10114 __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 10115 MacroAssembler::VELEM_SIZE_16, 0); 10116 %} 10117 ins_pipe( ialu_reg_reg ); // FIXME 10118%} 10119 10120instruct vmul8S_reg(vecX dst, vecX src1, vecX src2) %{ 10121 predicate(n->as_Vector()->length() == 8); 10122 match(Set dst (MulVS src1 src2)); 10123 size(4); 10124 format %{ "VMUL.I16 $dst.Q,$src1.Q,$src2.Q\t! mul packed8S" %} 10125 ins_encode %{ 10126 __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 10127 MacroAssembler::VELEM_SIZE_16, 1); 10128 %} 10129 ins_pipe( ialu_reg_reg ); // FIXME 10130%} 10131 10132// Integers vector mul 10133instruct vmul2I_reg(vecD dst, vecD src1, vecD src2) %{ 10134 predicate(n->as_Vector()->length() == 2); 10135 match(Set dst (MulVI src1 src2)); 10136 size(4); 10137 format %{ "VMUL.I32 $dst,$src1,$src2\t! mul packed2I" %} 10138 ins_encode %{ 10139 __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 10140 MacroAssembler::VELEM_SIZE_32, 0); 10141 %} 10142 ins_pipe( ialu_reg_reg ); // FIXME 10143%} 10144 10145instruct vmul4I_reg(vecX dst, vecX src1, vecX src2) %{ 10146 predicate(n->as_Vector()->length() == 4); 10147 match(Set dst (MulVI src1 src2)); 10148 size(4); 10149 format %{ "VMUL.I32 $dst.Q,$src1.Q,$src2.Q\t! mul packed4I" %} 10150 ins_encode %{ 10151 __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 10152 MacroAssembler::VELEM_SIZE_32, 1); 10153 %} 10154 ins_pipe( ialu_reg_reg ); // FIXME 10155%} 10156 10157// Floats vector mul 10158instruct vmul2F_reg(vecD dst, vecD src1, vecD src2) %{ 10159 predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant()); 10160 match(Set dst (MulVF src1 src2)); 10161 size(4); 10162 format %{ "VMUL.F32 $dst,$src1,$src2\t! mul packed2F" %} 10163 ins_encode %{ 10164 __ vmulF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 10165 MacroAssembler::VFA_SIZE_F32, 0); 10166 %} 10167 ins_pipe( fmulF_reg_reg ); // FIXME 10168%} 10169 10170instruct vmul2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{ 10171 predicate(n->as_Vector()->length() == 2 && !VM_Version::simd_math_is_compliant()); 10172 match(Set dst (MulVF src1 src2)); 10173 size(4*2); 10174 ins_cost(DEFAULT_COST*2); // FIXME 10175 10176 format %{ "FMULS $dst.a,$src1.a,$src2.a\n\t" 10177 "FMULS $dst.b,$src1.b,$src2.b" %} 10178 ins_encode %{ 10179 __ mul_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 10180 __ mul_float($dst$$FloatRegister->successor(), 10181 $src1$$FloatRegister->successor(), 10182 $src2$$FloatRegister->successor()); 10183 %} 10184 10185 ins_pipe(fmulF_reg_reg); // FIXME 10186%} 10187 10188instruct vmul4F_reg(vecX dst, vecX src1, vecX src2) %{ 10189 predicate(n->as_Vector()->length() == 4 && VM_Version::simd_math_is_compliant()); 10190 match(Set dst (MulVF src1 src2)); 10191 size(4); 10192 format %{ "VMUL.F32 $dst.Q,$src1.Q,$src2.Q\t! mul packed4F" %} 10193 ins_encode %{ 10194 __ vmulF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 10195 MacroAssembler::VFA_SIZE_F32, 1); 10196 %} 10197 ins_pipe( fmulF_reg_reg ); // FIXME 10198%} 10199 10200instruct vmul4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 10201 predicate(n->as_Vector()->length() == 4 && !VM_Version::simd_math_is_compliant()); 10202 match(Set dst (MulVF src1 src2)); 10203 size(4*4); 10204 ins_cost(DEFAULT_COST*4); // FIXME 10205 10206 format %{ "FMULS $dst.a,$src1.a,$src2.a\n\t" 10207 "FMULS $dst.b,$src1.b,$src2.b\n\t" 10208 "FMULS $dst.c,$src1.c,$src2.c\n\t" 10209 "FMULS $dst.d,$src1.d,$src2.d" %} 10210 10211 ins_encode %{ 10212 FloatRegister dsta = $dst$$FloatRegister; 10213 FloatRegister src1a = $src1$$FloatRegister; 10214 FloatRegister src2a = $src2$$FloatRegister; 10215 __ mul_float(dsta, src1a, src2a); 10216 FloatRegister dstb = dsta->successor(); 10217 FloatRegister src1b = src1a->successor(); 10218 FloatRegister src2b = src2a->successor(); 10219 __ mul_float(dstb, src1b, src2b); 10220 FloatRegister dstc = dstb->successor(); 10221 FloatRegister src1c = src1b->successor(); 10222 FloatRegister src2c = src2b->successor(); 10223 __ mul_float(dstc, src1c, src2c); 10224 FloatRegister dstd = dstc->successor(); 10225 FloatRegister src1d = src1c->successor(); 10226 FloatRegister src2d = src2c->successor(); 10227 __ mul_float(dstd, src1d, src2d); 10228 %} 10229 10230 ins_pipe(fmulF_reg_reg); // FIXME 10231%} 10232 10233instruct vmul2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 10234 predicate(n->as_Vector()->length() == 2); 10235 match(Set dst (MulVD src1 src2)); 10236 size(4*2); 10237 ins_cost(DEFAULT_COST*2); // FIXME 10238 10239 format %{ "FMULD $dst.D.a,$src1.D.a,$src2.D.a\n\t" 10240 "FMULD $dst.D.b,$src1.D.b,$src2.D.b" %} 10241 ins_encode %{ 10242 FloatRegister dsta = $dst$$FloatRegister; 10243 FloatRegister src1a = $src1$$FloatRegister; 10244 FloatRegister src2a = $src2$$FloatRegister; 10245 __ mul_double(dsta, src1a, src2a); 10246 FloatRegister dstb = dsta->successor()->successor(); 10247 FloatRegister src1b = src1a->successor()->successor(); 10248 FloatRegister src2b = src2a->successor()->successor(); 10249 __ mul_double(dstb, src1b, src2b); 10250 %} 10251 10252 ins_pipe(fmulD_reg_reg); // FIXME 10253%} 10254 10255 10256// Floats vector div 10257instruct vdiv2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{ 10258 predicate(n->as_Vector()->length() == 2); 10259 match(Set dst (DivVF src1 src2)); 10260 size(4*2); 10261 ins_cost(DEFAULT_COST*2); // FIXME 10262 10263 format %{ "FDIVS $dst.a,$src1.a,$src2.a\n\t" 10264 "FDIVS $dst.b,$src1.b,$src2.b" %} 10265 ins_encode %{ 10266 __ div_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 10267 __ div_float($dst$$FloatRegister->successor(), 10268 $src1$$FloatRegister->successor(), 10269 $src2$$FloatRegister->successor()); 10270 %} 10271 10272 ins_pipe(fdivF_reg_reg); // FIXME 10273%} 10274 10275instruct vdiv4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 10276 predicate(n->as_Vector()->length() == 4); 10277 match(Set dst (DivVF src1 src2)); 10278 size(4*4); 10279 ins_cost(DEFAULT_COST*4); // FIXME 10280 10281 format %{ "FDIVS $dst.a,$src1.a,$src2.a\n\t" 10282 "FDIVS $dst.b,$src1.b,$src2.b\n\t" 10283 "FDIVS $dst.c,$src1.c,$src2.c\n\t" 10284 "FDIVS $dst.d,$src1.d,$src2.d" %} 10285 10286 ins_encode %{ 10287 FloatRegister dsta = $dst$$FloatRegister; 10288 FloatRegister src1a = $src1$$FloatRegister; 10289 FloatRegister src2a = $src2$$FloatRegister; 10290 __ div_float(dsta, src1a, src2a); 10291 FloatRegister dstb = dsta->successor(); 10292 FloatRegister src1b = src1a->successor(); 10293 FloatRegister src2b = src2a->successor(); 10294 __ div_float(dstb, src1b, src2b); 10295 FloatRegister dstc = dstb->successor(); 10296 FloatRegister src1c = src1b->successor(); 10297 FloatRegister src2c = src2b->successor(); 10298 __ div_float(dstc, src1c, src2c); 10299 FloatRegister dstd = dstc->successor(); 10300 FloatRegister src1d = src1c->successor(); 10301 FloatRegister src2d = src2c->successor(); 10302 __ div_float(dstd, src1d, src2d); 10303 %} 10304 10305 ins_pipe(fdivF_reg_reg); // FIXME 10306%} 10307 10308instruct vdiv2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 10309 predicate(n->as_Vector()->length() == 2); 10310 match(Set dst (DivVD src1 src2)); 10311 size(4*2); 10312 ins_cost(DEFAULT_COST*2); // FIXME 10313 10314 format %{ "FDIVD $dst.D.a,$src1.D.a,$src2.D.a\n\t" 10315 "FDIVD $dst.D.b,$src1.D.b,$src2.D.b" %} 10316 ins_encode %{ 10317 FloatRegister dsta = $dst$$FloatRegister; 10318 FloatRegister src1a = $src1$$FloatRegister; 10319 FloatRegister src2a = $src2$$FloatRegister; 10320 __ div_double(dsta, src1a, src2a); 10321 FloatRegister dstb = dsta->successor()->successor(); 10322 FloatRegister src1b = src1a->successor()->successor(); 10323 FloatRegister src2b = src2a->successor()->successor(); 10324 __ div_double(dstb, src1b, src2b); 10325 %} 10326 10327 ins_pipe(fdivD_reg_reg); // FIXME 10328%} 10329 10330// --------------------------------- NEG -------------------------------------- 10331 10332instruct vneg8B_reg(vecD dst, vecD src) %{ 10333 predicate(n->as_Vector()->length_in_bytes() == 8); 10334 effect(DEF dst, USE src); 10335 size(4); 10336 ins_cost(DEFAULT_COST); // FIXME 10337 format %{ "VNEG.S8 $dst.D,$src.D\t! neg packed8B" %} 10338 ins_encode %{ 10339 bool quad = false; 10340 __ vnegI($dst$$FloatRegister, $src$$FloatRegister, 10341 MacroAssembler::VELEM_SIZE_8, quad); 10342 %} 10343 ins_pipe( ialu_reg_reg ); // FIXME 10344%} 10345 10346instruct vneg16B_reg(vecX dst, vecX src) %{ 10347 predicate(n->as_Vector()->length_in_bytes() == 16); 10348 effect(DEF dst, USE src); 10349 size(4); 10350 ins_cost(DEFAULT_COST); // FIXME 10351 format %{ "VNEG.S8 $dst.Q,$src.Q\t! neg0 packed16B" %} 10352 ins_encode %{ 10353 bool _float = false; 10354 bool quad = true; 10355 __ vnegI($dst$$FloatRegister, $src$$FloatRegister, 10356 MacroAssembler::VELEM_SIZE_8, quad); 10357 %} 10358 ins_pipe( ialu_reg_reg ); // FIXME 10359%} 10360 10361// ------------------------------ Shift --------------------------------------- 10362 10363instruct vslcntD(vecD dst, iRegI cnt) %{ 10364 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 10365 match(Set dst (LShiftCntV cnt)); 10366 size(4); 10367 ins_cost(DEFAULT_COST); // FIXME 10368 expand %{ 10369 Repl8B_reg_simd(dst, cnt); 10370 %} 10371%} 10372 10373instruct vslcntX(vecX dst, iRegI cnt) %{ 10374 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 10375 match(Set dst (LShiftCntV cnt)); 10376 size(4); 10377 ins_cost(DEFAULT_COST); // FIXME 10378 expand %{ 10379 Repl16B_reg(dst, cnt); 10380 %} 10381%} 10382 10383// Low bits of vector "shift" elements are used, so it 10384// doesn't matter if we treat it as ints or bytes here. 10385instruct vsrcntD(vecD dst, iRegI cnt) %{ 10386 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 10387 match(Set dst (RShiftCntV cnt)); 10388 size(4*2); 10389 ins_cost(DEFAULT_COST*2); // FIXME 10390 10391 format %{ "VDUP.8 $dst.D,$cnt\n\t" 10392 "VNEG.S8 $dst.D,$dst.D\t! neg packed8B" %} 10393 ins_encode %{ 10394 bool quad = false; 10395 __ vdupI($dst$$FloatRegister, $cnt$$Register, 10396 MacroAssembler::VELEM_SIZE_8, quad); 10397 __ vnegI($dst$$FloatRegister, $dst$$FloatRegister, 10398 MacroAssembler::VELEM_SIZE_8, quad); 10399 %} 10400 ins_pipe( ialu_reg_reg ); // FIXME 10401%} 10402 10403instruct vsrcntX(vecX dst, iRegI cnt) %{ 10404 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 10405 match(Set dst (RShiftCntV cnt)); 10406 size(4*2); 10407 ins_cost(DEFAULT_COST*2); // FIXME 10408 format %{ "VDUP.8 $dst.Q,$cnt\n\t" 10409 "VNEG.S8 $dst.Q,$dst.Q\t! neg packed16B" %} 10410 ins_encode %{ 10411 bool quad = true; 10412 __ vdupI($dst$$FloatRegister, $cnt$$Register, 10413 MacroAssembler::VELEM_SIZE_8, quad); 10414 __ vnegI($dst$$FloatRegister, $dst$$FloatRegister, 10415 MacroAssembler::VELEM_SIZE_8, quad); 10416 %} 10417 ins_pipe( ialu_reg_reg ); // FIXME 10418%} 10419 10420// Byte vector logical left/right shift based on sign 10421instruct vsh8B_reg(vecD dst, vecD src, vecD shift) %{ 10422 predicate(n->as_Vector()->length() == 8); 10423 effect(DEF dst, USE src, USE shift); 10424 size(4); 10425 ins_cost(DEFAULT_COST); // FIXME 10426 format %{ 10427 "VSHL.U8 $dst.D,$src.D,$shift.D\t! logical left/right shift packed8B" 10428 %} 10429 ins_encode %{ 10430 bool quad = false; 10431 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 10432 MacroAssembler::VELEM_SIZE_8, quad); 10433 %} 10434 ins_pipe( ialu_reg_reg ); // FIXME 10435%} 10436 10437instruct vsh16B_reg(vecX dst, vecX src, vecX shift) %{ 10438 predicate(n->as_Vector()->length() == 16); 10439 effect(DEF dst, USE src, USE shift); 10440 size(4); 10441 ins_cost(DEFAULT_COST); // FIXME 10442 format %{ 10443 "VSHL.U8 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed16B" 10444 %} 10445 ins_encode %{ 10446 bool quad = true; 10447 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 10448 MacroAssembler::VELEM_SIZE_8, quad); 10449 %} 10450 ins_pipe( ialu_reg_reg ); // FIXME 10451%} 10452 10453// Shorts/Char vector logical left/right shift based on sign 10454instruct vsh4S_reg(vecD dst, vecD src, vecD shift) %{ 10455 predicate(n->as_Vector()->length() == 4); 10456 effect(DEF dst, USE src, USE shift); 10457 size(4); 10458 ins_cost(DEFAULT_COST); // FIXME 10459 format %{ 10460 "VSHL.U16 $dst.D,$src.D,$shift.D\t! logical left/right shift packed4S" 10461 %} 10462 ins_encode %{ 10463 bool quad = false; 10464 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 10465 MacroAssembler::VELEM_SIZE_16, quad); 10466 %} 10467 ins_pipe( ialu_reg_reg ); // FIXME 10468%} 10469 10470instruct vsh8S_reg(vecX dst, vecX src, vecX shift) %{ 10471 predicate(n->as_Vector()->length() == 8); 10472 effect(DEF dst, USE src, USE shift); 10473 size(4); 10474 ins_cost(DEFAULT_COST); // FIXME 10475 format %{ 10476 "VSHL.U16 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed8S" 10477 %} 10478 ins_encode %{ 10479 bool quad = true; 10480 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 10481 MacroAssembler::VELEM_SIZE_16, quad); 10482 %} 10483 ins_pipe( ialu_reg_reg ); // FIXME 10484%} 10485 10486// Integers vector logical left/right shift based on sign 10487instruct vsh2I_reg(vecD dst, vecD src, vecD shift) %{ 10488 predicate(n->as_Vector()->length() == 2); 10489 effect(DEF dst, USE src, USE shift); 10490 size(4); 10491 ins_cost(DEFAULT_COST); // FIXME 10492 format %{ 10493 "VSHL.U32 $dst.D,$src.D,$shift.D\t! logical left/right shift packed2I" 10494 %} 10495 ins_encode %{ 10496 bool quad = false; 10497 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 10498 MacroAssembler::VELEM_SIZE_32, quad); 10499 %} 10500 ins_pipe( ialu_reg_reg ); // FIXME 10501%} 10502 10503instruct vsh4I_reg(vecX dst, vecX src, vecX shift) %{ 10504 predicate(n->as_Vector()->length() == 4); 10505 effect(DEF dst, USE src, USE shift); 10506 size(4); 10507 ins_cost(DEFAULT_COST); // FIXME 10508 format %{ 10509 "VSHL.U32 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed4I" 10510 %} 10511 ins_encode %{ 10512 bool quad = true; 10513 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 10514 MacroAssembler::VELEM_SIZE_32, quad); 10515 %} 10516 ins_pipe( ialu_reg_reg ); // FIXME 10517%} 10518 10519// Longs vector logical left/right shift based on sign 10520instruct vsh2L_reg(vecX dst, vecX src, vecX shift) %{ 10521 predicate(n->as_Vector()->length() == 2); 10522 effect(DEF dst, USE src, USE shift); 10523 size(4); 10524 ins_cost(DEFAULT_COST); // FIXME 10525 format %{ 10526 "VSHL.U64 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed2L" 10527 %} 10528 ins_encode %{ 10529 bool quad = true; 10530 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 10531 MacroAssembler::VELEM_SIZE_64, quad); 10532 %} 10533 ins_pipe( ialu_reg_reg ); // FIXME 10534%} 10535 10536// ------------------------------ LeftShift ----------------------------------- 10537 10538// Byte vector left shift 10539instruct vsl8B_reg(vecD dst, vecD src, vecD shift) %{ 10540 predicate(n->as_Vector()->length() == 8); 10541 match(Set dst (LShiftVB src shift)); 10542 size(4*1); 10543 ins_cost(DEFAULT_COST*1); // FIXME 10544 expand %{ 10545 vsh8B_reg(dst, src, shift); 10546 %} 10547%} 10548 10549instruct vsl16B_reg(vecX dst, vecX src, vecX shift) %{ 10550 predicate(n->as_Vector()->length() == 16); 10551 match(Set dst (LShiftVB src shift)); 10552 size(4*1); 10553 ins_cost(DEFAULT_COST*1); // FIXME 10554 expand %{ 10555 vsh16B_reg(dst, src, shift); 10556 %} 10557%} 10558 10559instruct vsl8B_immI(vecD dst, vecD src, immI shift) %{ 10560 predicate(n->as_Vector()->length() == 8); 10561 match(Set dst (LShiftVB src (LShiftCntV shift))); 10562 size(4); 10563 ins_cost(DEFAULT_COST); // FIXME 10564 format %{ 10565 "VSHL.I8 $dst.D,$src.D,$shift\t! logical left shift packed8B" 10566 %} 10567 ins_encode %{ 10568 bool quad = false; 10569 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant, 10570 quad); 10571 %} 10572 ins_pipe( ialu_reg_reg ); // FIXME 10573%} 10574 10575instruct vsl16B_immI(vecX dst, vecX src, immI shift) %{ 10576 predicate(n->as_Vector()->length() == 16); 10577 match(Set dst (LShiftVB src (LShiftCntV shift))); 10578 size(4); 10579 ins_cost(DEFAULT_COST); // FIXME 10580 format %{ 10581 "VSHL.I8 $dst.Q,$src.Q,$shift\t! logical left shift packed16B" 10582 %} 10583 ins_encode %{ 10584 bool quad = true; 10585 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant, 10586 quad); 10587 %} 10588 ins_pipe( ialu_reg_reg ); // FIXME 10589%} 10590 10591// Shorts/Chars vector logical left/right shift 10592instruct vsl4S_reg(vecD dst, vecD src, vecD shift) %{ 10593 predicate(n->as_Vector()->length() == 4); 10594 match(Set dst (LShiftVS src shift)); 10595 match(Set dst (URShiftVS src shift)); 10596 size(4*1); 10597 ins_cost(DEFAULT_COST*1); // FIXME 10598 expand %{ 10599 vsh4S_reg(dst, src, shift); 10600 %} 10601%} 10602 10603instruct vsl8S_reg(vecX dst, vecX src, vecX shift) %{ 10604 predicate(n->as_Vector()->length() == 8); 10605 match(Set dst (LShiftVS src shift)); 10606 match(Set dst (URShiftVS src shift)); 10607 size(4*1); 10608 ins_cost(DEFAULT_COST*1); // FIXME 10609 expand %{ 10610 vsh8S_reg(dst, src, shift); 10611 %} 10612%} 10613 10614instruct vsl4S_immI(vecD dst, vecD src, immI shift) %{ 10615 predicate(n->as_Vector()->length() == 4); 10616 match(Set dst (LShiftVS src (LShiftCntV shift))); 10617 size(4); 10618 ins_cost(DEFAULT_COST); // FIXME 10619 format %{ 10620 "VSHL.I16 $dst.D,$src.D,$shift\t! logical left shift packed4S" 10621 %} 10622 ins_encode %{ 10623 bool quad = false; 10624 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant, 10625 quad); 10626 %} 10627 ins_pipe( ialu_reg_reg ); // FIXME 10628%} 10629 10630instruct vsl8S_immI(vecX dst, vecX src, immI shift) %{ 10631 predicate(n->as_Vector()->length() == 8); 10632 match(Set dst (LShiftVS src shift)); 10633 size(4); 10634 ins_cost(DEFAULT_COST); // FIXME 10635 format %{ 10636 "VSHL.I16 $dst.Q,$src.Q,$shift\t! logical left shift packed8S" 10637 %} 10638 ins_encode %{ 10639 bool quad = true; 10640 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant, 10641 quad); 10642 %} 10643 ins_pipe( ialu_reg_reg ); // FIXME 10644%} 10645 10646// Integers vector logical left/right shift 10647instruct vsl2I_reg(vecD dst, vecD src, vecD shift) %{ 10648 predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd()); 10649 match(Set dst (LShiftVI src shift)); 10650 match(Set dst (URShiftVI src shift)); 10651 size(4*1); 10652 ins_cost(DEFAULT_COST*1); // FIXME 10653 expand %{ 10654 vsh2I_reg(dst, src, shift); 10655 %} 10656%} 10657 10658instruct vsl4I_reg(vecX dst, vecX src, vecX shift) %{ 10659 predicate(n->as_Vector()->length() == 4 && VM_Version::has_simd()); 10660 match(Set dst (LShiftVI src shift)); 10661 match(Set dst (URShiftVI src shift)); 10662 size(4*1); 10663 ins_cost(DEFAULT_COST*1); // FIXME 10664 expand %{ 10665 vsh4I_reg(dst, src, shift); 10666 %} 10667%} 10668 10669instruct vsl2I_immI(vecD dst, vecD src, immI shift) %{ 10670 predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd()); 10671 match(Set dst (LShiftVI src (LShiftCntV shift))); 10672 size(4); 10673 ins_cost(DEFAULT_COST); // FIXME 10674 format %{ 10675 "VSHL.I32 $dst.D,$src.D,$shift\t! logical left shift packed2I" 10676 %} 10677 ins_encode %{ 10678 bool quad = false; 10679 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant, 10680 quad); 10681 %} 10682 ins_pipe( ialu_reg_reg ); // FIXME 10683%} 10684 10685instruct vsl4I_immI(vecX dst, vecX src, immI shift) %{ 10686 predicate(n->as_Vector()->length() == 4 && VM_Version::has_simd()); 10687 match(Set dst (LShiftVI src (LShiftCntV shift))); 10688 size(4); 10689 ins_cost(DEFAULT_COST); // FIXME 10690 format %{ 10691 "VSHL.I32 $dst.Q,$src.Q,$shift\t! logical left shift packed4I" 10692 %} 10693 ins_encode %{ 10694 bool quad = true; 10695 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant, 10696 quad); 10697 %} 10698 ins_pipe( ialu_reg_reg ); // FIXME 10699%} 10700 10701// Longs vector logical left/right shift 10702instruct vsl2L_reg(vecX dst, vecX src, vecX shift) %{ 10703 predicate(n->as_Vector()->length() == 2); 10704 match(Set dst (LShiftVL src shift)); 10705 match(Set dst (URShiftVL src shift)); 10706 size(4*1); 10707 ins_cost(DEFAULT_COST*1); // FIXME 10708 expand %{ 10709 vsh2L_reg(dst, src, shift); 10710 %} 10711%} 10712 10713instruct vsl2L_immI(vecX dst, vecX src, immI shift) %{ 10714 predicate(n->as_Vector()->length() == 2); 10715 match(Set dst (LShiftVL src (LShiftCntV shift))); 10716 size(4); 10717 ins_cost(DEFAULT_COST); // FIXME 10718 format %{ 10719 "VSHL.I64 $dst.Q,$src.Q,$shift\t! logical left shift packed2L" 10720 %} 10721 ins_encode %{ 10722 bool quad = true; 10723 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 64, $shift$$constant, 10724 quad); 10725 %} 10726 ins_pipe( ialu_reg_reg ); // FIXME 10727%} 10728 10729// ----------------------- LogicalRightShift ----------------------------------- 10730 10731// Bytes/Shorts vector logical right shift produces incorrect Java result 10732// for negative data because java code convert short value into int with 10733// sign extension before a shift. 10734 10735// Chars vector logical right shift 10736instruct vsrl4S_immI(vecD dst, vecD src, immI shift) %{ 10737 predicate(n->as_Vector()->length() == 4); 10738 match(Set dst (URShiftVS src (RShiftCntV shift))); 10739 size(4); 10740 ins_cost(DEFAULT_COST); // FIXME 10741 format %{ 10742 "VSHR.U16 $dst.D,$src.D,$shift\t! logical right shift packed4S" 10743 %} 10744 ins_encode %{ 10745 bool quad = false; 10746 __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant, 10747 quad); 10748 %} 10749 ins_pipe( ialu_reg_reg ); // FIXME 10750%} 10751 10752instruct vsrl8S_immI(vecX dst, vecX src, immI shift) %{ 10753 predicate(n->as_Vector()->length() == 8); 10754 match(Set dst (URShiftVS src (RShiftCntV shift))); 10755 size(4); 10756 ins_cost(DEFAULT_COST); // FIXME 10757 format %{ 10758 "VSHR.U16 $dst.Q,$src.Q,$shift\t! logical right shift packed8S" 10759 %} 10760 ins_encode %{ 10761 bool quad = true; 10762 __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant, 10763 quad); 10764 %} 10765 ins_pipe( ialu_reg_reg ); // FIXME 10766%} 10767 10768// Integers vector logical right shift 10769instruct vsrl2I_immI(vecD dst, vecD src, immI shift) %{ 10770 predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd()); 10771 match(Set dst (URShiftVI src (RShiftCntV shift))); 10772 size(4); 10773 ins_cost(DEFAULT_COST); // FIXME 10774 format %{ 10775 "VSHR.U32 $dst.D,$src.D,$shift\t! logical right shift packed2I" 10776 %} 10777 ins_encode %{ 10778 bool quad = false; 10779 __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant, 10780 quad); 10781 %} 10782 ins_pipe( ialu_reg_reg ); // FIXME 10783%} 10784 10785instruct vsrl4I_immI(vecX dst, vecX src, immI shift) %{ 10786 predicate(n->as_Vector()->length() == 4 && VM_Version::has_simd()); 10787 match(Set dst (URShiftVI src (RShiftCntV shift))); 10788 size(4); 10789 ins_cost(DEFAULT_COST); // FIXME 10790 format %{ 10791 "VSHR.U32 $dst.Q,$src.Q,$shift\t! logical right shift packed4I" 10792 %} 10793 ins_encode %{ 10794 bool quad = true; 10795 __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant, 10796 quad); 10797 %} 10798 ins_pipe( ialu_reg_reg ); // FIXME 10799%} 10800 10801// Longs vector logical right shift 10802instruct vsrl2L_immI(vecX dst, vecX src, immI shift) %{ 10803 predicate(n->as_Vector()->length() == 2); 10804 match(Set dst (URShiftVL src (RShiftCntV shift))); 10805 size(4); 10806 ins_cost(DEFAULT_COST); // FIXME 10807 format %{ 10808 "VSHR.U64 $dst.Q,$src.Q,$shift\t! logical right shift packed2L" 10809 %} 10810 ins_encode %{ 10811 bool quad = true; 10812 __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 64, $shift$$constant, 10813 quad); 10814 %} 10815 ins_pipe( ialu_reg_reg ); // FIXME 10816%} 10817 10818// ------------------- ArithmeticRightShift ----------------------------------- 10819 10820// Bytes vector arithmetic left/right shift based on sign 10821instruct vsha8B_reg(vecD dst, vecD src, vecD shift) %{ 10822 predicate(n->as_Vector()->length() == 8); 10823 effect(DEF dst, USE src, USE shift); 10824 size(4); 10825 ins_cost(DEFAULT_COST); // FIXME 10826 format %{ 10827 "VSHL.S8 $dst.D,$src.D,$shift.D\t! arithmetic right shift packed8B" 10828 %} 10829 ins_encode %{ 10830 bool quad = false; 10831 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 10832 MacroAssembler::VELEM_SIZE_8, quad); 10833 %} 10834 ins_pipe( ialu_reg_reg ); // FIXME 10835%} 10836 10837instruct vsha16B_reg(vecX dst, vecX src, vecX shift) %{ 10838 predicate(n->as_Vector()->length() == 16); 10839 effect(DEF dst, USE src, USE shift); 10840 size(4); 10841 ins_cost(DEFAULT_COST); // FIXME 10842 format %{ 10843 "VSHL.S8 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed16B" 10844 %} 10845 ins_encode %{ 10846 bool quad = true; 10847 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 10848 MacroAssembler::VELEM_SIZE_8, quad); 10849 %} 10850 ins_pipe( ialu_reg_reg ); // FIXME 10851%} 10852 10853// Shorts vector arithmetic left/right shift based on sign 10854instruct vsha4S_reg(vecD dst, vecD src, vecD shift) %{ 10855 predicate(n->as_Vector()->length() == 4); 10856 effect(DEF dst, USE src, USE shift); 10857 size(4); 10858 ins_cost(DEFAULT_COST); // FIXME 10859 format %{ 10860 "VSHL.S16 $dst.D,$src.D,$shift.D\t! arithmetic right shift packed4S" 10861 %} 10862 ins_encode %{ 10863 bool quad = false; 10864 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 10865 MacroAssembler::VELEM_SIZE_16, quad); 10866 %} 10867 ins_pipe( ialu_reg_reg ); // FIXME 10868%} 10869 10870instruct vsha8S_reg(vecX dst, vecX src, vecX shift) %{ 10871 predicate(n->as_Vector()->length() == 8); 10872 effect(DEF dst, USE src, USE shift); 10873 size(4); 10874 ins_cost(DEFAULT_COST); // FIXME 10875 format %{ 10876 "VSHL.S16 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed8S" 10877 %} 10878 ins_encode %{ 10879 bool quad = true; 10880 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 10881 MacroAssembler::VELEM_SIZE_16, quad); 10882 %} 10883 ins_pipe( ialu_reg_reg ); // FIXME 10884%} 10885 10886// Integers vector arithmetic left/right shift based on sign 10887instruct vsha2I_reg(vecD dst, vecD src, vecD shift) %{ 10888 predicate(n->as_Vector()->length() == 2); 10889 effect(DEF dst, USE src, USE shift); 10890 size(4); 10891 ins_cost(DEFAULT_COST); // FIXME 10892 format %{ 10893 "VSHL.S32 $dst.D,$src.D,$shift.D\t! arithmetic right shift packed2I" 10894 %} 10895 ins_encode %{ 10896 bool quad = false; 10897 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 10898 MacroAssembler::VELEM_SIZE_32, quad); 10899 %} 10900 ins_pipe( ialu_reg_reg ); // FIXME 10901%} 10902 10903instruct vsha4I_reg(vecX dst, vecX src, vecX shift) %{ 10904 predicate(n->as_Vector()->length() == 4); 10905 effect(DEF dst, USE src, USE shift); 10906 size(4); 10907 ins_cost(DEFAULT_COST); // FIXME 10908 format %{ 10909 "VSHL.S32 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed4I" 10910 %} 10911 ins_encode %{ 10912 bool quad = true; 10913 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 10914 MacroAssembler::VELEM_SIZE_32, quad); 10915 %} 10916 ins_pipe( ialu_reg_reg ); // FIXME 10917%} 10918 10919// Longs vector arithmetic left/right shift based on sign 10920instruct vsha2L_reg(vecX dst, vecX src, vecX shift) %{ 10921 predicate(n->as_Vector()->length() == 2); 10922 effect(DEF dst, USE src, USE shift); 10923 size(4); 10924 ins_cost(DEFAULT_COST); // FIXME 10925 format %{ 10926 "VSHL.S64 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed2L" 10927 %} 10928 ins_encode %{ 10929 bool quad = true; 10930 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 10931 MacroAssembler::VELEM_SIZE_64, quad); 10932 %} 10933 ins_pipe( ialu_reg_reg ); // FIXME 10934%} 10935 10936// Byte vector arithmetic right shift 10937 10938instruct vsra8B_reg(vecD dst, vecD src, vecD shift) %{ 10939 predicate(n->as_Vector()->length() == 8); 10940 match(Set dst (RShiftVB src shift)); 10941 size(4); 10942 ins_cost(DEFAULT_COST); // FIXME 10943 expand %{ 10944 vsha8B_reg(dst, src, shift); 10945 %} 10946%} 10947 10948instruct vsrl16B_reg(vecX dst, vecX src, vecX shift) %{ 10949 predicate(n->as_Vector()->length() == 16); 10950 match(Set dst (RShiftVB src shift)); 10951 size(4); 10952 ins_cost(DEFAULT_COST); // FIXME 10953 expand %{ 10954 vsha16B_reg(dst, src, shift); 10955 %} 10956%} 10957 10958instruct vsrl8B_immI(vecD dst, vecD src, immI shift) %{ 10959 predicate(n->as_Vector()->length() == 8); 10960 match(Set dst (RShiftVB src shift)); 10961 size(4); 10962 ins_cost(DEFAULT_COST); // FIXME 10963 format %{ 10964 "VSHR.S8 $dst.D,$src.D,$shift\t! logical right shift packed8B" 10965 %} 10966 ins_encode %{ 10967 bool quad = false; 10968 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant, 10969 quad); 10970 %} 10971 ins_pipe( ialu_reg_reg ); // FIXME 10972%} 10973 10974instruct vsrl16B_immI(vecX dst, vecX src, immI shift) %{ 10975 predicate(n->as_Vector()->length() == 16); 10976 match(Set dst (RShiftVB src shift)); 10977 size(4); 10978 ins_cost(DEFAULT_COST); // FIXME 10979 format %{ 10980 "VSHR.S8 $dst.Q,$src.Q,$shift\t! logical right shift packed16B" 10981 %} 10982 ins_encode %{ 10983 bool quad = true; 10984 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant, 10985 quad); 10986 %} 10987 ins_pipe( ialu_reg_reg ); // FIXME 10988%} 10989 10990// Shorts vector arithmetic right shift 10991instruct vsra4S_reg(vecD dst, vecD src, vecD shift) %{ 10992 predicate(n->as_Vector()->length() == 4); 10993 match(Set dst (RShiftVS src shift)); 10994 size(4); 10995 ins_cost(DEFAULT_COST); // FIXME 10996 expand %{ 10997 vsha4S_reg(dst, src, shift); 10998 %} 10999%} 11000 11001instruct vsra8S_reg(vecX dst, vecX src, vecX shift) %{ 11002 predicate(n->as_Vector()->length() == 8); 11003 match(Set dst (RShiftVS src shift)); 11004 size(4); 11005 ins_cost(DEFAULT_COST); // FIXME 11006 expand %{ 11007 vsha8S_reg(dst, src, shift); 11008 %} 11009%} 11010 11011instruct vsra4S_immI(vecD dst, vecD src, immI shift) %{ 11012 predicate(n->as_Vector()->length() == 4); 11013 match(Set dst (RShiftVS src shift)); 11014 size(4); 11015 ins_cost(DEFAULT_COST); // FIXME 11016 format %{ 11017 "VSHR.S16 $dst.D,$src.D,$shift\t! logical right shift packed4S" 11018 %} 11019 ins_encode %{ 11020 bool quad = false; 11021 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant, 11022 quad); 11023 %} 11024 ins_pipe( ialu_reg_reg ); // FIXME 11025%} 11026 11027instruct vsra8S_immI(vecX dst, vecX src, immI shift) %{ 11028 predicate(n->as_Vector()->length() == 8); 11029 match(Set dst (RShiftVS src shift)); 11030 size(4); 11031 ins_cost(DEFAULT_COST); // FIXME 11032 format %{ 11033 "VSHR.S16 $dst.Q,$src.Q,$shift\t! logical right shift packed8S" 11034 %} 11035 ins_encode %{ 11036 bool quad = true; 11037 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant, 11038 quad); 11039 %} 11040 ins_pipe( ialu_reg_reg ); // FIXME 11041%} 11042 11043// Integers vector arithmetic right shift 11044instruct vsra2I_reg(vecD dst, vecD src, vecD shift) %{ 11045 predicate(n->as_Vector()->length() == 2); 11046 match(Set dst (RShiftVI src shift)); 11047 size(4); 11048 ins_cost(DEFAULT_COST); // FIXME 11049 expand %{ 11050 vsha2I_reg(dst, src, shift); 11051 %} 11052%} 11053 11054instruct vsra4I_reg(vecX dst, vecX src, vecX shift) %{ 11055 predicate(n->as_Vector()->length() == 4); 11056 match(Set dst (RShiftVI src shift)); 11057 size(4); 11058 ins_cost(DEFAULT_COST); // FIXME 11059 expand %{ 11060 vsha4I_reg(dst, src, shift); 11061 %} 11062%} 11063 11064instruct vsra2I_immI(vecD dst, vecD src, immI shift) %{ 11065 predicate(n->as_Vector()->length() == 2); 11066 match(Set dst (RShiftVI src shift)); 11067 size(4); 11068 ins_cost(DEFAULT_COST); // FIXME 11069 format %{ 11070 "VSHR.S32 $dst.D,$src.D,$shift\t! logical right shift packed2I" 11071 %} 11072 ins_encode %{ 11073 bool quad = false; 11074 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant, 11075 quad); 11076 %} 11077 ins_pipe( ialu_reg_reg ); // FIXME 11078%} 11079 11080instruct vsra4I_immI(vecX dst, vecX src, immI shift) %{ 11081 predicate(n->as_Vector()->length() == 4); 11082 match(Set dst (RShiftVI src shift)); 11083 size(4); 11084 ins_cost(DEFAULT_COST); // FIXME 11085 format %{ 11086 "VSHR.S32 $dst.Q,$src.Q,$shift\t! logical right shift packed4I" 11087 %} 11088 ins_encode %{ 11089 bool quad = true; 11090 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant, 11091 quad); 11092 %} 11093 ins_pipe( ialu_reg_reg ); // FIXME 11094%} 11095 11096// Longs vector arithmetic right shift 11097instruct vsra2L_reg(vecX dst, vecX src, vecX shift) %{ 11098 predicate(n->as_Vector()->length() == 2); 11099 match(Set dst (RShiftVL src shift)); 11100 size(4); 11101 ins_cost(DEFAULT_COST); // FIXME 11102 expand %{ 11103 vsha2L_reg(dst, src, shift); 11104 %} 11105%} 11106 11107instruct vsra2L_immI(vecX dst, vecX src, immI shift) %{ 11108 predicate(n->as_Vector()->length() == 2); 11109 match(Set dst (RShiftVL src shift)); 11110 size(4); 11111 ins_cost(DEFAULT_COST); // FIXME 11112 format %{ 11113 "VSHR.S64 $dst.Q,$src.Q,$shift\t! logical right shift packed2L" 11114 %} 11115 ins_encode %{ 11116 bool quad = true; 11117 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 64, $shift$$constant, 11118 quad); 11119 %} 11120 ins_pipe( ialu_reg_reg ); // FIXME 11121%} 11122 11123// --------------------------------- AND -------------------------------------- 11124 11125instruct vandD(vecD dst, vecD src1, vecD src2) %{ 11126 predicate(n->as_Vector()->length_in_bytes() == 8); 11127 match(Set dst (AndV src1 src2)); 11128 format %{ "VAND $dst.D,$src1.D,$src2.D\t! and vectors (8 bytes)" %} 11129 ins_encode %{ 11130 bool quad = false; 11131 __ vandI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 11132 quad); 11133 %} 11134 ins_pipe( ialu_reg_reg ); // FIXME 11135%} 11136 11137instruct vandX(vecX dst, vecX src1, vecX src2) %{ 11138 predicate(n->as_Vector()->length_in_bytes() == 16); 11139 match(Set dst (AndV src1 src2)); 11140 format %{ "VAND $dst.Q,$src1.Q,$src2.Q\t! and vectors (16 bytes)" %} 11141 ins_encode %{ 11142 bool quad = true; 11143 __ vandI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 11144 quad); 11145 %} 11146 ins_pipe( ialu_reg_reg ); // FIXME 11147%} 11148 11149// --------------------------------- OR --------------------------------------- 11150 11151instruct vorD(vecD dst, vecD src1, vecD src2) %{ 11152 predicate(n->as_Vector()->length_in_bytes() == 8); 11153 match(Set dst (OrV src1 src2)); 11154 format %{ "VOR $dst.D,$src1.D,$src2.D\t! and vectors (8 bytes)" %} 11155 ins_encode %{ 11156 bool quad = false; 11157 __ vorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 11158 quad); 11159 %} 11160 ins_pipe( ialu_reg_reg ); // FIXME 11161%} 11162 11163instruct vorX(vecX dst, vecX src1, vecX src2) %{ 11164 predicate(n->as_Vector()->length_in_bytes() == 16); 11165 match(Set dst (OrV src1 src2)); 11166 format %{ "VOR $dst.Q,$src1.Q,$src2.Q\t! and vectors (16 bytes)" %} 11167 ins_encode %{ 11168 bool quad = true; 11169 __ vorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 11170 quad); 11171 %} 11172 ins_pipe( ialu_reg_reg ); // FIXME 11173%} 11174 11175// --------------------------------- XOR -------------------------------------- 11176 11177instruct vxorD(vecD dst, vecD src1, vecD src2) %{ 11178 predicate(n->as_Vector()->length_in_bytes() == 8); 11179 match(Set dst (XorV src1 src2)); 11180 format %{ "VXOR $dst.D,$src1.D,$src2.D\t! and vectors (8 bytes)" %} 11181 ins_encode %{ 11182 bool quad = false; 11183 __ vxorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 11184 quad); 11185 %} 11186 ins_pipe( ialu_reg_reg ); // FIXME 11187%} 11188 11189instruct vxorX(vecX dst, vecX src1, vecX src2) %{ 11190 predicate(n->as_Vector()->length_in_bytes() == 16); 11191 match(Set dst (XorV src1 src2)); 11192 format %{ "VXOR $dst.Q,$src1.Q,$src2.Q\t! and vectors (16 bytes)" %} 11193 ins_encode %{ 11194 bool quad = true; 11195 __ vxorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 11196 quad); 11197 %} 11198 ins_pipe( ialu_reg_reg ); // FIXME 11199%} 11200 11201 11202//----------PEEPHOLE RULES----------------------------------------------------- 11203// These must follow all instruction definitions as they use the names 11204// defined in the instructions definitions. 11205// 11206// peepmatch ( root_instr_name [preceding_instruction]* ); 11207// 11208// peepconstraint %{ 11209// (instruction_number.operand_name relational_op instruction_number.operand_name 11210// [, ...] ); 11211// // instruction numbers are zero-based using left to right order in peepmatch 11212// 11213// peepreplace ( instr_name ( [instruction_number.operand_name]* ) ); 11214// // provide an instruction_number.operand_name for each operand that appears 11215// // in the replacement instruction's match rule 11216// 11217// ---------VM FLAGS--------------------------------------------------------- 11218// 11219// All peephole optimizations can be turned off using -XX:-OptoPeephole 11220// 11221// Each peephole rule is given an identifying number starting with zero and 11222// increasing by one in the order seen by the parser. An individual peephole 11223// can be enabled, and all others disabled, by using -XX:OptoPeepholeAt=# 11224// on the command-line. 11225// 11226// ---------CURRENT LIMITATIONS---------------------------------------------- 11227// 11228// Only match adjacent instructions in same basic block 11229// Only equality constraints 11230// Only constraints between operands, not (0.dest_reg == EAX_enc) 11231// Only one replacement instruction 11232// 11233// ---------EXAMPLE---------------------------------------------------------- 11234// 11235// // pertinent parts of existing instructions in architecture description 11236// instruct movI(eRegI dst, eRegI src) %{ 11237// match(Set dst (CopyI src)); 11238// %} 11239// 11240// instruct incI_eReg(eRegI dst, immI1 src, eFlagsReg cr) %{ 11241// match(Set dst (AddI dst src)); 11242// effect(KILL cr); 11243// %} 11244// 11245// // Change (inc mov) to lea 11246// peephole %{ 11247// // increment preceeded by register-register move 11248// peepmatch ( incI_eReg movI ); 11249// // require that the destination register of the increment 11250// // match the destination register of the move 11251// peepconstraint ( 0.dst == 1.dst ); 11252// // construct a replacement instruction that sets 11253// // the destination to ( move's source register + one ) 11254// peepreplace ( incI_eReg_immI1( 0.dst 1.src 0.src ) ); 11255// %} 11256// 11257 11258// // Change load of spilled value to only a spill 11259// instruct storeI(memory mem, eRegI src) %{ 11260// match(Set mem (StoreI mem src)); 11261// %} 11262// 11263// instruct loadI(eRegI dst, memory mem) %{ 11264// match(Set dst (LoadI mem)); 11265// %} 11266// 11267// peephole %{ 11268// peepmatch ( loadI storeI ); 11269// peepconstraint ( 1.src == 0.dst, 1.mem == 0.mem ); 11270// peepreplace ( storeI( 1.mem 1.mem 1.src ) ); 11271// %} 11272 11273//----------SMARTSPILL RULES--------------------------------------------------- 11274// These must follow all instruction definitions as they use the names 11275// defined in the instructions definitions. 11276// 11277// ARM will probably not have any of these rules due to RISC instruction set. 11278 11279//----------PIPELINE----------------------------------------------------------- 11280// Rules which define the behavior of the target architectures pipeline. 11281