4528 // Condition Code Register used by long compare
4529 operand flagsReg_long_LTGE() %{
4530 constraint(ALLOC_IN_RC(int_flags));
4531 match(RegFlags);
4532 format %{ "FLAGS_LTGE" %}
4533 interface(REG_INTER);
4534 %}
4535 operand flagsReg_long_EQNE() %{
4536 constraint(ALLOC_IN_RC(int_flags));
4537 match(RegFlags);
4538 format %{ "FLAGS_EQNE" %}
4539 interface(REG_INTER);
4540 %}
4541 operand flagsReg_long_LEGT() %{
4542 constraint(ALLOC_IN_RC(int_flags));
4543 match(RegFlags);
4544 format %{ "FLAGS_LEGT" %}
4545 interface(REG_INTER);
4546 %}
4547
4548 // Float register operands
4549 operand regDPR() %{
4550 predicate( UseSSE < 2 );
4551 constraint(ALLOC_IN_RC(fp_dbl_reg));
4552 match(RegD);
4553 match(regDPR1);
4554 match(regDPR2);
4555 format %{ %}
4556 interface(REG_INTER);
4557 %}
4558
4559 operand regDPR1(regDPR reg) %{
4560 predicate( UseSSE < 2 );
4561 constraint(ALLOC_IN_RC(fp_dbl_reg0));
4562 match(reg);
4563 format %{ "FPR1" %}
4564 interface(REG_INTER);
4565 %}
4566
4567 operand regDPR2(regDPR reg) %{
5041 less_equal(0x6, "be");
5042 greater(0x7, "nbe");
5043 %}
5044 %}
5045
5046 // Comparison Code for FP conditional move
5047 operand cmpOp_fcmov() %{
5048 match(Bool);
5049
5050 format %{ "" %}
5051 interface(COND_INTER) %{
5052 equal (0x0C8);
5053 not_equal (0x1C8);
5054 less (0x0C0);
5055 greater_equal(0x1C0);
5056 less_equal (0x0D0);
5057 greater (0x1D0);
5058 %}
5059 %}
5060
5061 // Comparision Code used in long compares
5062 operand cmpOp_commute() %{
5063 match(Bool);
5064
5065 format %{ "" %}
5066 interface(COND_INTER) %{
5067 equal(0x4, "e");
5068 not_equal(0x5, "ne");
5069 less(0xF, "g");
5070 greater_equal(0xE, "le");
5071 less_equal(0xD, "ge");
5072 greater(0xC, "l");
5073 %}
5074 %}
5075
5076 //----------OPERAND CLASSES----------------------------------------------------
5077 // Operand Classes are groups of operands that are used as to simplify
5078 // instruction definitions by not requiring the AD writer to specify separate
5079 // instructions for every form of operand when the instruction accepts
5080 // multiple operand types with the same basic encoding and format. The classic
5081 // case of this is memory operands.
5082
5083 opclass memory(direct, indirect, indOffset8, indOffset32, indOffset32X, indIndexOffset,
5084 indIndex, indIndexScale, indIndexScaleOffset);
5085
5086 // Long memory operations are encoded in 2 instructions and a +4 offset.
5087 // This means some kind of offset is always required and you cannot use
5088 // an oop as the offset (done when working on static globals).
5089 opclass long_memory(direct, indirect, indOffset8, indOffset32, indIndexOffset,
5090 indIndex, indIndexScale, indIndexScaleOffset);
5091
5092
5093 //----------PIPELINE-----------------------------------------------------------
5094 // Rules which define the behavior of the target architectures pipeline.
5095 pipeline %{
12485 effect( TEMP tmp );
12486 ins_cost(300);
12487 format %{ "CMP $src1.lo,$src2.lo\t! Long compare; set flags for low bits\n\t"
12488 "MOV $tmp,$src1.hi\n\t"
12489 "SBB $tmp,$src2.hi\t! Compute flags for long compare" %}
12490 ins_encode( long_cmp_flags2( src1, src2, tmp ) );
12491 ins_pipe( ialu_cr_reg_reg );
12492 %}
12493
12494 // Long compares reg < zero/req OR reg >= zero/req.
12495 // Just a wrapper for a normal branch, plus the predicate test.
12496 instruct cmpL_LTGE(cmpOp cmp, flagsReg_long_LTGE flags, label labl) %{
12497 match(If cmp flags);
12498 effect(USE labl);
12499 predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge );
12500 expand %{
12501 jmpCon(cmp,flags,labl); // JLT or JGE...
12502 %}
12503 %}
12504
12505 // Compare 2 longs and CMOVE longs.
12506 instruct cmovLL_reg_LTGE(cmpOp cmp, flagsReg_long_LTGE flags, eRegL dst, eRegL src) %{
12507 match(Set dst (CMoveL (Binary cmp flags) (Binary dst src)));
12508 predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ));
12509 ins_cost(400);
12510 format %{ "CMOV$cmp $dst.lo,$src.lo\n\t"
12511 "CMOV$cmp $dst.hi,$src.hi" %}
12512 opcode(0x0F,0x40);
12513 ins_encode( enc_cmov(cmp), RegReg_Lo2( dst, src ), enc_cmov(cmp), RegReg_Hi2( dst, src ) );
12514 ins_pipe( pipe_cmov_reg_long );
12515 %}
12516
12517 instruct cmovLL_mem_LTGE(cmpOp cmp, flagsReg_long_LTGE flags, eRegL dst, load_long_memory src) %{
12518 match(Set dst (CMoveL (Binary cmp flags) (Binary dst (LoadL src))));
12519 predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ));
12520 ins_cost(500);
12521 format %{ "CMOV$cmp $dst.lo,$src.lo\n\t"
12522 "CMOV$cmp $dst.hi,$src.hi" %}
12523 opcode(0x0F,0x40);
12524 ins_encode( enc_cmov(cmp), RegMem(dst, src), enc_cmov(cmp), RegMem_Hi(dst, src) );
12613 ins_cost(200+300);
12614 format %{ "CMP $src1.lo,$src2.lo\t! Long compare; set flags for low bits\n\t"
12615 "JNE,s skip\n\t"
12616 "CMP $src1.hi,$src2.hi\n\t"
12617 "skip:\t" %}
12618 ins_encode( long_cmp_flags1( src1, src2 ) );
12619 ins_pipe( ialu_cr_reg_reg );
12620 %}
12621
12622 // Long compare reg == zero/reg OR reg != zero/reg
12623 // Just a wrapper for a normal branch, plus the predicate test.
12624 instruct cmpL_EQNE(cmpOp cmp, flagsReg_long_EQNE flags, label labl) %{
12625 match(If cmp flags);
12626 effect(USE labl);
12627 predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne );
12628 expand %{
12629 jmpCon(cmp,flags,labl); // JEQ or JNE...
12630 %}
12631 %}
12632
12633 // Compare 2 longs and CMOVE longs.
12634 instruct cmovLL_reg_EQNE(cmpOp cmp, flagsReg_long_EQNE flags, eRegL dst, eRegL src) %{
12635 match(Set dst (CMoveL (Binary cmp flags) (Binary dst src)));
12636 predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ));
12637 ins_cost(400);
12638 format %{ "CMOV$cmp $dst.lo,$src.lo\n\t"
12639 "CMOV$cmp $dst.hi,$src.hi" %}
12640 opcode(0x0F,0x40);
12641 ins_encode( enc_cmov(cmp), RegReg_Lo2( dst, src ), enc_cmov(cmp), RegReg_Hi2( dst, src ) );
12642 ins_pipe( pipe_cmov_reg_long );
12643 %}
12644
12645 instruct cmovLL_mem_EQNE(cmpOp cmp, flagsReg_long_EQNE flags, eRegL dst, load_long_memory src) %{
12646 match(Set dst (CMoveL (Binary cmp flags) (Binary dst (LoadL src))));
12647 predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ));
12648 ins_cost(500);
12649 format %{ "CMOV$cmp $dst.lo,$src.lo\n\t"
12650 "CMOV$cmp $dst.hi,$src.hi" %}
12651 opcode(0x0F,0x40);
12652 ins_encode( enc_cmov(cmp), RegMem(dst, src), enc_cmov(cmp), RegMem_Hi(dst, src) );
12743 instruct cmpL_reg_flags_LEGT( flagsReg_long_LEGT flags, eRegL src1, eRegL src2, rRegI tmp ) %{
12744 match( Set flags (CmpL src1 src2 ));
12745 effect( TEMP tmp );
12746 ins_cost(300);
12747 format %{ "CMP $src2.lo,$src1.lo\t! Long compare, swapped operands, use with commuted test\n\t"
12748 "MOV $tmp,$src2.hi\n\t"
12749 "SBB $tmp,$src1.hi\t! Compute flags for long compare" %}
12750 ins_encode( long_cmp_flags2( src2, src1, tmp ) );
12751 ins_pipe( ialu_cr_reg_reg );
12752 %}
12753
12754 // Long compares reg < zero/req OR reg >= zero/req.
12755 // Just a wrapper for a normal branch, plus the predicate test
12756 instruct cmpL_LEGT(cmpOp_commute cmp, flagsReg_long_LEGT flags, label labl) %{
12757 match(If cmp flags);
12758 effect(USE labl);
12759 predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le );
12760 ins_cost(300);
12761 expand %{
12762 jmpCon(cmp,flags,labl); // JGT or JLE...
12763 %}
12764 %}
12765
12766 // Compare 2 longs and CMOVE longs.
12767 instruct cmovLL_reg_LEGT(cmpOp_commute cmp, flagsReg_long_LEGT flags, eRegL dst, eRegL src) %{
12768 match(Set dst (CMoveL (Binary cmp flags) (Binary dst src)));
12769 predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ));
12770 ins_cost(400);
12771 format %{ "CMOV$cmp $dst.lo,$src.lo\n\t"
12772 "CMOV$cmp $dst.hi,$src.hi" %}
12773 opcode(0x0F,0x40);
12774 ins_encode( enc_cmov(cmp), RegReg_Lo2( dst, src ), enc_cmov(cmp), RegReg_Hi2( dst, src ) );
12775 ins_pipe( pipe_cmov_reg_long );
12776 %}
12777
12778 instruct cmovLL_mem_LEGT(cmpOp_commute cmp, flagsReg_long_LEGT flags, eRegL dst, load_long_memory src) %{
12779 match(Set dst (CMoveL (Binary cmp flags) (Binary dst (LoadL src))));
12780 predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ));
12781 ins_cost(500);
12782 format %{ "CMOV$cmp $dst.lo,$src.lo\n\t"
|
4528 // Condition Code Register used by long compare
4529 operand flagsReg_long_LTGE() %{
4530 constraint(ALLOC_IN_RC(int_flags));
4531 match(RegFlags);
4532 format %{ "FLAGS_LTGE" %}
4533 interface(REG_INTER);
4534 %}
4535 operand flagsReg_long_EQNE() %{
4536 constraint(ALLOC_IN_RC(int_flags));
4537 match(RegFlags);
4538 format %{ "FLAGS_EQNE" %}
4539 interface(REG_INTER);
4540 %}
4541 operand flagsReg_long_LEGT() %{
4542 constraint(ALLOC_IN_RC(int_flags));
4543 match(RegFlags);
4544 format %{ "FLAGS_LEGT" %}
4545 interface(REG_INTER);
4546 %}
4547
4548 // Condition Code Register used by unsigned long compare
4549 operand flagsReg_ulong_LTGE() %{
4550 constraint(ALLOC_IN_RC(int_flags));
4551 match(RegFlags);
4552 format %{ "FLAGS_U_LTGE" %}
4553 interface(REG_INTER);
4554 %}
4555 operand flagsReg_ulong_EQNE() %{
4556 constraint(ALLOC_IN_RC(int_flags));
4557 match(RegFlags);
4558 format %{ "FLAGS_U_EQNE" %}
4559 interface(REG_INTER);
4560 %}
4561 operand flagsReg_ulong_LEGT() %{
4562 constraint(ALLOC_IN_RC(int_flags));
4563 match(RegFlags);
4564 format %{ "FLAGS_U_LEGT" %}
4565 interface(REG_INTER);
4566 %}
4567
4568 // Float register operands
4569 operand regDPR() %{
4570 predicate( UseSSE < 2 );
4571 constraint(ALLOC_IN_RC(fp_dbl_reg));
4572 match(RegD);
4573 match(regDPR1);
4574 match(regDPR2);
4575 format %{ %}
4576 interface(REG_INTER);
4577 %}
4578
4579 operand regDPR1(regDPR reg) %{
4580 predicate( UseSSE < 2 );
4581 constraint(ALLOC_IN_RC(fp_dbl_reg0));
4582 match(reg);
4583 format %{ "FPR1" %}
4584 interface(REG_INTER);
4585 %}
4586
4587 operand regDPR2(regDPR reg) %{
5061 less_equal(0x6, "be");
5062 greater(0x7, "nbe");
5063 %}
5064 %}
5065
5066 // Comparison Code for FP conditional move
5067 operand cmpOp_fcmov() %{
5068 match(Bool);
5069
5070 format %{ "" %}
5071 interface(COND_INTER) %{
5072 equal (0x0C8);
5073 not_equal (0x1C8);
5074 less (0x0C0);
5075 greater_equal(0x1C0);
5076 less_equal (0x0D0);
5077 greater (0x1D0);
5078 %}
5079 %}
5080
5081 // Comparison Code used in long compares
5082 operand cmpOp_commute() %{
5083 match(Bool);
5084
5085 format %{ "" %}
5086 interface(COND_INTER) %{
5087 equal(0x4, "e");
5088 not_equal(0x5, "ne");
5089 less(0xF, "g");
5090 greater_equal(0xE, "le");
5091 less_equal(0xD, "ge");
5092 greater(0xC, "l");
5093 %}
5094 %}
5095
5096 // Comparison Code used in unsigned long compares
5097 operand cmpOpU_commute() %{
5098 match(Bool);
5099
5100 format %{ "" %}
5101 interface(COND_INTER) %{
5102 equal(0x4, "e");
5103 not_equal(0x5, "ne");
5104 less(0x7, "nbe");
5105 greater_equal(0x6, "be");
5106 less_equal(0x3, "nb");
5107 greater(0x2, "b");
5108 %}
5109 %}
5110
5111 //----------OPERAND CLASSES----------------------------------------------------
5112 // Operand Classes are groups of operands that are used as to simplify
5113 // instruction definitions by not requiring the AD writer to specify separate
5114 // instructions for every form of operand when the instruction accepts
5115 // multiple operand types with the same basic encoding and format. The classic
5116 // case of this is memory operands.
5117
5118 opclass memory(direct, indirect, indOffset8, indOffset32, indOffset32X, indIndexOffset,
5119 indIndex, indIndexScale, indIndexScaleOffset);
5120
5121 // Long memory operations are encoded in 2 instructions and a +4 offset.
5122 // This means some kind of offset is always required and you cannot use
5123 // an oop as the offset (done when working on static globals).
5124 opclass long_memory(direct, indirect, indOffset8, indOffset32, indIndexOffset,
5125 indIndex, indIndexScale, indIndexScaleOffset);
5126
5127
5128 //----------PIPELINE-----------------------------------------------------------
5129 // Rules which define the behavior of the target architectures pipeline.
5130 pipeline %{
12520 effect( TEMP tmp );
12521 ins_cost(300);
12522 format %{ "CMP $src1.lo,$src2.lo\t! Long compare; set flags for low bits\n\t"
12523 "MOV $tmp,$src1.hi\n\t"
12524 "SBB $tmp,$src2.hi\t! Compute flags for long compare" %}
12525 ins_encode( long_cmp_flags2( src1, src2, tmp ) );
12526 ins_pipe( ialu_cr_reg_reg );
12527 %}
12528
12529 // Long compares reg < zero/req OR reg >= zero/req.
12530 // Just a wrapper for a normal branch, plus the predicate test.
12531 instruct cmpL_LTGE(cmpOp cmp, flagsReg_long_LTGE flags, label labl) %{
12532 match(If cmp flags);
12533 effect(USE labl);
12534 predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge );
12535 expand %{
12536 jmpCon(cmp,flags,labl); // JLT or JGE...
12537 %}
12538 %}
12539
12540 //======
12541 // Manifest a CmpUL result in the normal flags. Only good for LT or GE
12542 // compares. Can be used for LE or GT compares by reversing arguments.
12543 // NOT GOOD FOR EQ/NE tests.
12544 instruct cmpUL_zero_flags_LTGE(flagsReg_ulong_LTGE flags, eRegL src, immL0 zero) %{
12545 match(Set flags (CmpUL src zero));
12546 ins_cost(100);
12547 format %{ "TEST $src.hi,$src.hi" %}
12548 opcode(0x85);
12549 ins_encode(OpcP, RegReg_Hi2(src, src));
12550 ins_pipe(ialu_cr_reg_reg);
12551 %}
12552
12553 // Manifest a CmpUL result in the normal flags. Only good for LT or GE
12554 // compares. Can be used for LE or GT compares by reversing arguments.
12555 // NOT GOOD FOR EQ/NE tests.
12556 instruct cmpUL_reg_flags_LTGE(flagsReg_ulong_LTGE flags, eRegL src1, eRegL src2, rRegI tmp) %{
12557 match(Set flags (CmpUL src1 src2));
12558 effect(TEMP tmp);
12559 ins_cost(300);
12560 format %{ "CMP $src1.lo,$src2.lo\t! Unsigned long compare; set flags for low bits\n\t"
12561 "MOV $tmp,$src1.hi\n\t"
12562 "SBB $tmp,$src2.hi\t! Compute flags for unsigned long compare" %}
12563 ins_encode(long_cmp_flags2(src1, src2, tmp));
12564 ins_pipe(ialu_cr_reg_reg);
12565 %}
12566
12567 // Unsigned long compares reg < zero/req OR reg >= zero/req.
12568 // Just a wrapper for a normal branch, plus the predicate test.
12569 instruct cmpUL_LTGE(cmpOpU cmp, flagsReg_ulong_LTGE flags, label labl) %{
12570 match(If cmp flags);
12571 effect(USE labl);
12572 predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
12573 expand %{
12574 jmpCon(cmp, flags, labl); // JLT or JGE...
12575 %}
12576 %}
12577
12578 // Compare 2 longs and CMOVE longs.
12579 instruct cmovLL_reg_LTGE(cmpOp cmp, flagsReg_long_LTGE flags, eRegL dst, eRegL src) %{
12580 match(Set dst (CMoveL (Binary cmp flags) (Binary dst src)));
12581 predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ));
12582 ins_cost(400);
12583 format %{ "CMOV$cmp $dst.lo,$src.lo\n\t"
12584 "CMOV$cmp $dst.hi,$src.hi" %}
12585 opcode(0x0F,0x40);
12586 ins_encode( enc_cmov(cmp), RegReg_Lo2( dst, src ), enc_cmov(cmp), RegReg_Hi2( dst, src ) );
12587 ins_pipe( pipe_cmov_reg_long );
12588 %}
12589
12590 instruct cmovLL_mem_LTGE(cmpOp cmp, flagsReg_long_LTGE flags, eRegL dst, load_long_memory src) %{
12591 match(Set dst (CMoveL (Binary cmp flags) (Binary dst (LoadL src))));
12592 predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ));
12593 ins_cost(500);
12594 format %{ "CMOV$cmp $dst.lo,$src.lo\n\t"
12595 "CMOV$cmp $dst.hi,$src.hi" %}
12596 opcode(0x0F,0x40);
12597 ins_encode( enc_cmov(cmp), RegMem(dst, src), enc_cmov(cmp), RegMem_Hi(dst, src) );
12686 ins_cost(200+300);
12687 format %{ "CMP $src1.lo,$src2.lo\t! Long compare; set flags for low bits\n\t"
12688 "JNE,s skip\n\t"
12689 "CMP $src1.hi,$src2.hi\n\t"
12690 "skip:\t" %}
12691 ins_encode( long_cmp_flags1( src1, src2 ) );
12692 ins_pipe( ialu_cr_reg_reg );
12693 %}
12694
12695 // Long compare reg == zero/reg OR reg != zero/reg
12696 // Just a wrapper for a normal branch, plus the predicate test.
12697 instruct cmpL_EQNE(cmpOp cmp, flagsReg_long_EQNE flags, label labl) %{
12698 match(If cmp flags);
12699 effect(USE labl);
12700 predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne );
12701 expand %{
12702 jmpCon(cmp,flags,labl); // JEQ or JNE...
12703 %}
12704 %}
12705
12706 //======
12707 // Manifest a CmpUL result in the normal flags. Only good for EQ/NE compares.
12708 instruct cmpUL_zero_flags_EQNE(flagsReg_ulong_EQNE flags, eRegL src, immL0 zero, rRegI tmp) %{
12709 match(Set flags (CmpUL src zero));
12710 effect(TEMP tmp);
12711 ins_cost(200);
12712 format %{ "MOV $tmp,$src.lo\n\t"
12713 "OR $tmp,$src.hi\t! Unsigned long is EQ/NE 0?" %}
12714 ins_encode(long_cmp_flags0(src, tmp));
12715 ins_pipe(ialu_reg_reg_long);
12716 %}
12717
12718 // Manifest a CmpUL result in the normal flags. Only good for EQ/NE compares.
12719 instruct cmpUL_reg_flags_EQNE(flagsReg_ulong_EQNE flags, eRegL src1, eRegL src2) %{
12720 match(Set flags (CmpUL src1 src2));
12721 ins_cost(200+300);
12722 format %{ "CMP $src1.lo,$src2.lo\t! Unsigned long compare; set flags for low bits\n\t"
12723 "JNE,s skip\n\t"
12724 "CMP $src1.hi,$src2.hi\n\t"
12725 "skip:\t" %}
12726 ins_encode(long_cmp_flags1(src1, src2));
12727 ins_pipe(ialu_cr_reg_reg);
12728 %}
12729
12730 // Unsigned long compare reg == zero/reg OR reg != zero/reg
12731 // Just a wrapper for a normal branch, plus the predicate test.
12732 instruct cmpUL_EQNE(cmpOpU cmp, flagsReg_ulong_EQNE flags, label labl) %{
12733 match(If cmp flags);
12734 effect(USE labl);
12735 predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
12736 expand %{
12737 jmpCon(cmp, flags, labl); // JEQ or JNE...
12738 %}
12739 %}
12740
12741 // Compare 2 longs and CMOVE longs.
12742 instruct cmovLL_reg_EQNE(cmpOp cmp, flagsReg_long_EQNE flags, eRegL dst, eRegL src) %{
12743 match(Set dst (CMoveL (Binary cmp flags) (Binary dst src)));
12744 predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ));
12745 ins_cost(400);
12746 format %{ "CMOV$cmp $dst.lo,$src.lo\n\t"
12747 "CMOV$cmp $dst.hi,$src.hi" %}
12748 opcode(0x0F,0x40);
12749 ins_encode( enc_cmov(cmp), RegReg_Lo2( dst, src ), enc_cmov(cmp), RegReg_Hi2( dst, src ) );
12750 ins_pipe( pipe_cmov_reg_long );
12751 %}
12752
12753 instruct cmovLL_mem_EQNE(cmpOp cmp, flagsReg_long_EQNE flags, eRegL dst, load_long_memory src) %{
12754 match(Set dst (CMoveL (Binary cmp flags) (Binary dst (LoadL src))));
12755 predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ));
12756 ins_cost(500);
12757 format %{ "CMOV$cmp $dst.lo,$src.lo\n\t"
12758 "CMOV$cmp $dst.hi,$src.hi" %}
12759 opcode(0x0F,0x40);
12760 ins_encode( enc_cmov(cmp), RegMem(dst, src), enc_cmov(cmp), RegMem_Hi(dst, src) );
12851 instruct cmpL_reg_flags_LEGT( flagsReg_long_LEGT flags, eRegL src1, eRegL src2, rRegI tmp ) %{
12852 match( Set flags (CmpL src1 src2 ));
12853 effect( TEMP tmp );
12854 ins_cost(300);
12855 format %{ "CMP $src2.lo,$src1.lo\t! Long compare, swapped operands, use with commuted test\n\t"
12856 "MOV $tmp,$src2.hi\n\t"
12857 "SBB $tmp,$src1.hi\t! Compute flags for long compare" %}
12858 ins_encode( long_cmp_flags2( src2, src1, tmp ) );
12859 ins_pipe( ialu_cr_reg_reg );
12860 %}
12861
12862 // Long compares reg < zero/req OR reg >= zero/req.
12863 // Just a wrapper for a normal branch, plus the predicate test
12864 instruct cmpL_LEGT(cmpOp_commute cmp, flagsReg_long_LEGT flags, label labl) %{
12865 match(If cmp flags);
12866 effect(USE labl);
12867 predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le );
12868 ins_cost(300);
12869 expand %{
12870 jmpCon(cmp,flags,labl); // JGT or JLE...
12871 %}
12872 %}
12873
12874 //======
12875 // Manifest a CmpUL result in the normal flags. Only good for LE or GT compares.
12876 // Same as cmpUL_reg_flags_LEGT except must negate src
12877 instruct cmpUL_zero_flags_LEGT(flagsReg_ulong_LEGT flags, eRegL src, immL0 zero, rRegI tmp) %{
12878 match(Set flags (CmpUL src zero));
12879 effect(TEMP tmp);
12880 ins_cost(300);
12881 format %{ "XOR $tmp,$tmp\t# Unsigned long compare for -$src < 0, use commuted test\n\t"
12882 "CMP $tmp,$src.lo\n\t"
12883 "SBB $tmp,$src.hi\n\t" %}
12884 ins_encode(long_cmp_flags3(src, tmp));
12885 ins_pipe(ialu_reg_reg_long);
12886 %}
12887
12888 // Manifest a CmpUL result in the normal flags. Only good for LE or GT compares.
12889 // Same as cmpUL_reg_flags_LTGE except operands swapped. Swapping operands
12890 // requires a commuted test to get the same result.
12891 instruct cmpUL_reg_flags_LEGT(flagsReg_ulong_LEGT flags, eRegL src1, eRegL src2, rRegI tmp) %{
12892 match(Set flags (CmpUL src1 src2));
12893 effect(TEMP tmp);
12894 ins_cost(300);
12895 format %{ "CMP $src2.lo,$src1.lo\t! Unsigned long compare, swapped operands, use with commuted test\n\t"
12896 "MOV $tmp,$src2.hi\n\t"
12897 "SBB $tmp,$src1.hi\t! Compute flags for unsigned long compare" %}
12898 ins_encode(long_cmp_flags2( src2, src1, tmp));
12899 ins_pipe(ialu_cr_reg_reg);
12900 %}
12901
12902 // Unsigned long compares reg < zero/req OR reg >= zero/req.
12903 // Just a wrapper for a normal branch, plus the predicate test
12904 instruct cmpUL_LEGT(cmpOpU_commute cmp, flagsReg_ulong_LEGT flags, label labl) %{
12905 match(If cmp flags);
12906 effect(USE labl);
12907 predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le);
12908 ins_cost(300);
12909 expand %{
12910 jmpCon(cmp, flags, labl); // JGT or JLE...
12911 %}
12912 %}
12913
12914 // Compare 2 longs and CMOVE longs.
12915 instruct cmovLL_reg_LEGT(cmpOp_commute cmp, flagsReg_long_LEGT flags, eRegL dst, eRegL src) %{
12916 match(Set dst (CMoveL (Binary cmp flags) (Binary dst src)));
12917 predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ));
12918 ins_cost(400);
12919 format %{ "CMOV$cmp $dst.lo,$src.lo\n\t"
12920 "CMOV$cmp $dst.hi,$src.hi" %}
12921 opcode(0x0F,0x40);
12922 ins_encode( enc_cmov(cmp), RegReg_Lo2( dst, src ), enc_cmov(cmp), RegReg_Hi2( dst, src ) );
12923 ins_pipe( pipe_cmov_reg_long );
12924 %}
12925
12926 instruct cmovLL_mem_LEGT(cmpOp_commute cmp, flagsReg_long_LEGT flags, eRegL dst, load_long_memory src) %{
12927 match(Set dst (CMoveL (Binary cmp flags) (Binary dst (LoadL src))));
12928 predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ));
12929 ins_cost(500);
12930 format %{ "CMOV$cmp $dst.lo,$src.lo\n\t"
|