Mercurial > hg > graal-jvmci-8
comparison src/cpu/x86/vm/x86_32.ad @ 415:4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
Reviewed-by: kvn, rasbold
author | never |
---|---|
date | Tue, 28 Oct 2008 09:31:30 -0700 |
parents | b744678d4d71 |
children | a1980da045cc |
comparison
equal
deleted
inserted
replaced
407:ebfd4ae89bf6 | 415:4d9884b01ba6 |
---|---|
493 //============================================================================= | 493 //============================================================================= |
494 #ifndef PRODUCT | 494 #ifndef PRODUCT |
495 void MachPrologNode::format( PhaseRegAlloc *ra_, outputStream* st ) const { | 495 void MachPrologNode::format( PhaseRegAlloc *ra_, outputStream* st ) const { |
496 Compile* C = ra_->C; | 496 Compile* C = ra_->C; |
497 if( C->in_24_bit_fp_mode() ) { | 497 if( C->in_24_bit_fp_mode() ) { |
498 tty->print("FLDCW 24 bit fpu control word"); | 498 st->print("FLDCW 24 bit fpu control word"); |
499 tty->print_cr(""); tty->print("\t"); | 499 st->print_cr(""); st->print("\t"); |
500 } | 500 } |
501 | 501 |
502 int framesize = C->frame_slots() << LogBytesPerInt; | 502 int framesize = C->frame_slots() << LogBytesPerInt; |
503 assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); | 503 assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); |
504 // Remove two words for return addr and rbp, | 504 // Remove two words for return addr and rbp, |
508 // We require that their callers must bang for them. But be careful, because | 508 // We require that their callers must bang for them. But be careful, because |
509 // some VM calls (such as call site linkage) can use several kilobytes of | 509 // some VM calls (such as call site linkage) can use several kilobytes of |
510 // stack. But the stack safety zone should account for that. | 510 // stack. But the stack safety zone should account for that. |
511 // See bugs 4446381, 4468289, 4497237. | 511 // See bugs 4446381, 4468289, 4497237. |
512 if (C->need_stack_bang(framesize)) { | 512 if (C->need_stack_bang(framesize)) { |
513 tty->print_cr("# stack bang"); tty->print("\t"); | 513 st->print_cr("# stack bang"); st->print("\t"); |
514 } | 514 } |
515 tty->print_cr("PUSHL EBP"); tty->print("\t"); | 515 st->print_cr("PUSHL EBP"); st->print("\t"); |
516 | 516 |
517 if( VerifyStackAtCalls ) { // Majik cookie to verify stack depth | 517 if( VerifyStackAtCalls ) { // Majik cookie to verify stack depth |
518 tty->print("PUSH 0xBADB100D\t# Majik cookie for stack depth check"); | 518 st->print("PUSH 0xBADB100D\t# Majik cookie for stack depth check"); |
519 tty->print_cr(""); tty->print("\t"); | 519 st->print_cr(""); st->print("\t"); |
520 framesize -= wordSize; | 520 framesize -= wordSize; |
521 } | 521 } |
522 | 522 |
523 if ((C->in_24_bit_fp_mode() || VerifyStackAtCalls ) && framesize < 128 ) { | 523 if ((C->in_24_bit_fp_mode() || VerifyStackAtCalls ) && framesize < 128 ) { |
524 if (framesize) { | 524 if (framesize) { |
525 tty->print("SUB ESP,%d\t# Create frame",framesize); | 525 st->print("SUB ESP,%d\t# Create frame",framesize); |
526 } | 526 } |
527 } else { | 527 } else { |
528 tty->print("SUB ESP,%d\t# Create frame",framesize); | 528 st->print("SUB ESP,%d\t# Create frame",framesize); |
529 } | 529 } |
530 } | 530 } |
531 #endif | 531 #endif |
532 | 532 |
533 | 533 |
723 } | 723 } |
724 assert(r->is_XMMRegister(), "must be"); | 724 assert(r->is_XMMRegister(), "must be"); |
725 return rc_xmm; | 725 return rc_xmm; |
726 } | 726 } |
727 | 727 |
728 static int impl_helper( CodeBuffer *cbuf, bool do_size, bool is_load, int offset, int reg, int opcode, const char *op_str, int size ) { | 728 static int impl_helper( CodeBuffer *cbuf, bool do_size, bool is_load, int offset, int reg, |
729 int opcode, const char *op_str, int size, outputStream* st ) { | |
729 if( cbuf ) { | 730 if( cbuf ) { |
730 emit_opcode (*cbuf, opcode ); | 731 emit_opcode (*cbuf, opcode ); |
731 encode_RegMem(*cbuf, Matcher::_regEncode[reg], ESP_enc, 0x4, 0, offset, false); | 732 encode_RegMem(*cbuf, Matcher::_regEncode[reg], ESP_enc, 0x4, 0, offset, false); |
732 #ifndef PRODUCT | 733 #ifndef PRODUCT |
733 } else if( !do_size ) { | 734 } else if( !do_size ) { |
734 if( size != 0 ) tty->print("\n\t"); | 735 if( size != 0 ) st->print("\n\t"); |
735 if( opcode == 0x8B || opcode == 0x89 ) { // MOV | 736 if( opcode == 0x8B || opcode == 0x89 ) { // MOV |
736 if( is_load ) tty->print("%s %s,[ESP + #%d]",op_str,Matcher::regName[reg],offset); | 737 if( is_load ) st->print("%s %s,[ESP + #%d]",op_str,Matcher::regName[reg],offset); |
737 else tty->print("%s [ESP + #%d],%s",op_str,offset,Matcher::regName[reg]); | 738 else st->print("%s [ESP + #%d],%s",op_str,offset,Matcher::regName[reg]); |
738 } else { // FLD, FST, PUSH, POP | 739 } else { // FLD, FST, PUSH, POP |
739 tty->print("%s [ESP + #%d]",op_str,offset); | 740 st->print("%s [ESP + #%d]",op_str,offset); |
740 } | 741 } |
741 #endif | 742 #endif |
742 } | 743 } |
743 int offset_size = (offset == 0) ? 0 : ((offset <= 127) ? 1 : 4); | 744 int offset_size = (offset == 0) ? 0 : ((offset <= 127) ? 1 : 4); |
744 return size+3+offset_size; | 745 return size+3+offset_size; |
745 } | 746 } |
746 | 747 |
747 // Helper for XMM registers. Extra opcode bits, limited syntax. | 748 // Helper for XMM registers. Extra opcode bits, limited syntax. |
748 static int impl_x_helper( CodeBuffer *cbuf, bool do_size, bool is_load, | 749 static int impl_x_helper( CodeBuffer *cbuf, bool do_size, bool is_load, |
749 int offset, int reg_lo, int reg_hi, int size ) { | 750 int offset, int reg_lo, int reg_hi, int size, outputStream* st ) { |
750 if( cbuf ) { | 751 if( cbuf ) { |
751 if( reg_lo+1 == reg_hi ) { // double move? | 752 if( reg_lo+1 == reg_hi ) { // double move? |
752 if( is_load && !UseXmmLoadAndClearUpper ) | 753 if( is_load && !UseXmmLoadAndClearUpper ) |
753 emit_opcode(*cbuf, 0x66 ); // use 'movlpd' for load | 754 emit_opcode(*cbuf, 0x66 ); // use 'movlpd' for load |
754 else | 755 else |
762 else | 763 else |
763 emit_opcode(*cbuf, is_load ? 0x10 : 0x11 ); | 764 emit_opcode(*cbuf, is_load ? 0x10 : 0x11 ); |
764 encode_RegMem(*cbuf, Matcher::_regEncode[reg_lo], ESP_enc, 0x4, 0, offset, false); | 765 encode_RegMem(*cbuf, Matcher::_regEncode[reg_lo], ESP_enc, 0x4, 0, offset, false); |
765 #ifndef PRODUCT | 766 #ifndef PRODUCT |
766 } else if( !do_size ) { | 767 } else if( !do_size ) { |
767 if( size != 0 ) tty->print("\n\t"); | 768 if( size != 0 ) st->print("\n\t"); |
768 if( reg_lo+1 == reg_hi ) { // double move? | 769 if( reg_lo+1 == reg_hi ) { // double move? |
769 if( is_load ) tty->print("%s %s,[ESP + #%d]", | 770 if( is_load ) st->print("%s %s,[ESP + #%d]", |
770 UseXmmLoadAndClearUpper ? "MOVSD " : "MOVLPD", | 771 UseXmmLoadAndClearUpper ? "MOVSD " : "MOVLPD", |
771 Matcher::regName[reg_lo], offset); | 772 Matcher::regName[reg_lo], offset); |
772 else tty->print("MOVSD [ESP + #%d],%s", | 773 else st->print("MOVSD [ESP + #%d],%s", |
773 offset, Matcher::regName[reg_lo]); | 774 offset, Matcher::regName[reg_lo]); |
774 } else { | 775 } else { |
775 if( is_load ) tty->print("MOVSS %s,[ESP + #%d]", | 776 if( is_load ) st->print("MOVSS %s,[ESP + #%d]", |
776 Matcher::regName[reg_lo], offset); | 777 Matcher::regName[reg_lo], offset); |
777 else tty->print("MOVSS [ESP + #%d],%s", | 778 else st->print("MOVSS [ESP + #%d],%s", |
778 offset, Matcher::regName[reg_lo]); | 779 offset, Matcher::regName[reg_lo]); |
779 } | 780 } |
780 #endif | 781 #endif |
781 } | 782 } |
782 int offset_size = (offset == 0) ? 0 : ((offset <= 127) ? 1 : 4); | 783 int offset_size = (offset == 0) ? 0 : ((offset <= 127) ? 1 : 4); |
783 return size+5+offset_size; | 784 return size+5+offset_size; |
784 } | 785 } |
785 | 786 |
786 | 787 |
787 static int impl_movx_helper( CodeBuffer *cbuf, bool do_size, int src_lo, int dst_lo, | 788 static int impl_movx_helper( CodeBuffer *cbuf, bool do_size, int src_lo, int dst_lo, |
788 int src_hi, int dst_hi, int size ) { | 789 int src_hi, int dst_hi, int size, outputStream* st ) { |
789 if( UseXmmRegToRegMoveAll ) {//Use movaps,movapd to move between xmm registers | 790 if( UseXmmRegToRegMoveAll ) {//Use movaps,movapd to move between xmm registers |
790 if( cbuf ) { | 791 if( cbuf ) { |
791 if( (src_lo+1 == src_hi && dst_lo+1 == dst_hi) ) { | 792 if( (src_lo+1 == src_hi && dst_lo+1 == dst_hi) ) { |
792 emit_opcode(*cbuf, 0x66 ); | 793 emit_opcode(*cbuf, 0x66 ); |
793 } | 794 } |
794 emit_opcode(*cbuf, 0x0F ); | 795 emit_opcode(*cbuf, 0x0F ); |
795 emit_opcode(*cbuf, 0x28 ); | 796 emit_opcode(*cbuf, 0x28 ); |
796 emit_rm (*cbuf, 0x3, Matcher::_regEncode[dst_lo], Matcher::_regEncode[src_lo] ); | 797 emit_rm (*cbuf, 0x3, Matcher::_regEncode[dst_lo], Matcher::_regEncode[src_lo] ); |
797 #ifndef PRODUCT | 798 #ifndef PRODUCT |
798 } else if( !do_size ) { | 799 } else if( !do_size ) { |
799 if( size != 0 ) tty->print("\n\t"); | 800 if( size != 0 ) st->print("\n\t"); |
800 if( src_lo+1 == src_hi && dst_lo+1 == dst_hi ) { // double move? | 801 if( src_lo+1 == src_hi && dst_lo+1 == dst_hi ) { // double move? |
801 tty->print("MOVAPD %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]); | 802 st->print("MOVAPD %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]); |
802 } else { | 803 } else { |
803 tty->print("MOVAPS %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]); | 804 st->print("MOVAPS %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]); |
804 } | 805 } |
805 #endif | 806 #endif |
806 } | 807 } |
807 return size + ((src_lo+1 == src_hi && dst_lo+1 == dst_hi) ? 4 : 3); | 808 return size + ((src_lo+1 == src_hi && dst_lo+1 == dst_hi) ? 4 : 3); |
808 } else { | 809 } else { |
811 emit_opcode(*cbuf, 0x0F ); | 812 emit_opcode(*cbuf, 0x0F ); |
812 emit_opcode(*cbuf, 0x10 ); | 813 emit_opcode(*cbuf, 0x10 ); |
813 emit_rm (*cbuf, 0x3, Matcher::_regEncode[dst_lo], Matcher::_regEncode[src_lo] ); | 814 emit_rm (*cbuf, 0x3, Matcher::_regEncode[dst_lo], Matcher::_regEncode[src_lo] ); |
814 #ifndef PRODUCT | 815 #ifndef PRODUCT |
815 } else if( !do_size ) { | 816 } else if( !do_size ) { |
816 if( size != 0 ) tty->print("\n\t"); | 817 if( size != 0 ) st->print("\n\t"); |
817 if( src_lo+1 == src_hi && dst_lo+1 == dst_hi ) { // double move? | 818 if( src_lo+1 == src_hi && dst_lo+1 == dst_hi ) { // double move? |
818 tty->print("MOVSD %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]); | 819 st->print("MOVSD %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]); |
819 } else { | 820 } else { |
820 tty->print("MOVSS %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]); | 821 st->print("MOVSS %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]); |
821 } | 822 } |
822 #endif | 823 #endif |
823 } | 824 } |
824 return size+4; | 825 return size+4; |
825 } | 826 } |
826 } | 827 } |
827 | 828 |
828 static int impl_mov_helper( CodeBuffer *cbuf, bool do_size, int src, int dst, int size ) { | 829 static int impl_mov_helper( CodeBuffer *cbuf, bool do_size, int src, int dst, int size, outputStream* st ) { |
829 if( cbuf ) { | 830 if( cbuf ) { |
830 emit_opcode(*cbuf, 0x8B ); | 831 emit_opcode(*cbuf, 0x8B ); |
831 emit_rm (*cbuf, 0x3, Matcher::_regEncode[dst], Matcher::_regEncode[src] ); | 832 emit_rm (*cbuf, 0x3, Matcher::_regEncode[dst], Matcher::_regEncode[src] ); |
832 #ifndef PRODUCT | 833 #ifndef PRODUCT |
833 } else if( !do_size ) { | 834 } else if( !do_size ) { |
834 if( size != 0 ) tty->print("\n\t"); | 835 if( size != 0 ) st->print("\n\t"); |
835 tty->print("MOV %s,%s",Matcher::regName[dst],Matcher::regName[src]); | 836 st->print("MOV %s,%s",Matcher::regName[dst],Matcher::regName[src]); |
836 #endif | 837 #endif |
837 } | 838 } |
838 return size+2; | 839 return size+2; |
839 } | 840 } |
840 | 841 |
841 static int impl_fp_store_helper( CodeBuffer *cbuf, bool do_size, int src_lo, int src_hi, int dst_lo, int dst_hi, int offset, int size ) { | 842 static int impl_fp_store_helper( CodeBuffer *cbuf, bool do_size, int src_lo, int src_hi, int dst_lo, int dst_hi, |
843 int offset, int size, outputStream* st ) { | |
842 if( src_lo != FPR1L_num ) { // Move value to top of FP stack, if not already there | 844 if( src_lo != FPR1L_num ) { // Move value to top of FP stack, if not already there |
843 if( cbuf ) { | 845 if( cbuf ) { |
844 emit_opcode( *cbuf, 0xD9 ); // FLD (i.e., push it) | 846 emit_opcode( *cbuf, 0xD9 ); // FLD (i.e., push it) |
845 emit_d8( *cbuf, 0xC0-1+Matcher::_regEncode[src_lo] ); | 847 emit_d8( *cbuf, 0xC0-1+Matcher::_regEncode[src_lo] ); |
846 #ifndef PRODUCT | 848 #ifndef PRODUCT |
847 } else if( !do_size ) { | 849 } else if( !do_size ) { |
848 if( size != 0 ) tty->print("\n\t"); | 850 if( size != 0 ) st->print("\n\t"); |
849 tty->print("FLD %s",Matcher::regName[src_lo]); | 851 st->print("FLD %s",Matcher::regName[src_lo]); |
850 #endif | 852 #endif |
851 } | 853 } |
852 size += 2; | 854 size += 2; |
853 } | 855 } |
854 | 856 |
862 op_str = (src_lo != FPR1L_num) ? "FSTP_S" : "FST_S "; | 864 op_str = (src_lo != FPR1L_num) ? "FSTP_S" : "FST_S "; |
863 op = 0xD9; | 865 op = 0xD9; |
864 assert( !OptoReg::is_valid(src_hi) && !OptoReg::is_valid(dst_hi), "no non-adjacent float-stores" ); | 866 assert( !OptoReg::is_valid(src_hi) && !OptoReg::is_valid(dst_hi), "no non-adjacent float-stores" ); |
865 } | 867 } |
866 | 868 |
867 return impl_helper(cbuf,do_size,false,offset,st_op,op,op_str,size); | 869 return impl_helper(cbuf,do_size,false,offset,st_op,op,op_str,size, st); |
868 } | 870 } |
869 | 871 |
870 uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, PhaseRegAlloc *ra_, bool do_size, outputStream* st ) const { | 872 uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, PhaseRegAlloc *ra_, bool do_size, outputStream* st ) const { |
871 // Get registers to move | 873 // Get registers to move |
872 OptoReg::Name src_second = ra_->get_reg_second(in(1)); | 874 OptoReg::Name src_second = ra_->get_reg_second(in(1)); |
890 // -------------------------------------- | 892 // -------------------------------------- |
891 // Check for mem-mem move. push/pop to move. | 893 // Check for mem-mem move. push/pop to move. |
892 if( src_first_rc == rc_stack && dst_first_rc == rc_stack ) { | 894 if( src_first_rc == rc_stack && dst_first_rc == rc_stack ) { |
893 if( src_second == dst_first ) { // overlapping stack copy ranges | 895 if( src_second == dst_first ) { // overlapping stack copy ranges |
894 assert( src_second_rc == rc_stack && dst_second_rc == rc_stack, "we only expect a stk-stk copy here" ); | 896 assert( src_second_rc == rc_stack && dst_second_rc == rc_stack, "we only expect a stk-stk copy here" ); |
895 size = impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_second),ESI_num,0xFF,"PUSH ",size); | 897 size = impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_second),ESI_num,0xFF,"PUSH ",size, st); |
896 size = impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_second),EAX_num,0x8F,"POP ",size); | 898 size = impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_second),EAX_num,0x8F,"POP ",size, st); |
897 src_second_rc = dst_second_rc = rc_bad; // flag as already moved the second bits | 899 src_second_rc = dst_second_rc = rc_bad; // flag as already moved the second bits |
898 } | 900 } |
899 // move low bits | 901 // move low bits |
900 size = impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_first),ESI_num,0xFF,"PUSH ",size); | 902 size = impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_first),ESI_num,0xFF,"PUSH ",size, st); |
901 size = impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_first),EAX_num,0x8F,"POP ",size); | 903 size = impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_first),EAX_num,0x8F,"POP ",size, st); |
902 if( src_second_rc == rc_stack && dst_second_rc == rc_stack ) { // mov second bits | 904 if( src_second_rc == rc_stack && dst_second_rc == rc_stack ) { // mov second bits |
903 size = impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_second),ESI_num,0xFF,"PUSH ",size); | 905 size = impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_second),ESI_num,0xFF,"PUSH ",size, st); |
904 size = impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_second),EAX_num,0x8F,"POP ",size); | 906 size = impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_second),EAX_num,0x8F,"POP ",size, st); |
905 } | 907 } |
906 return size; | 908 return size; |
907 } | 909 } |
908 | 910 |
909 // -------------------------------------- | 911 // -------------------------------------- |
910 // Check for integer reg-reg copy | 912 // Check for integer reg-reg copy |
911 if( src_first_rc == rc_int && dst_first_rc == rc_int ) | 913 if( src_first_rc == rc_int && dst_first_rc == rc_int ) |
912 size = impl_mov_helper(cbuf,do_size,src_first,dst_first,size); | 914 size = impl_mov_helper(cbuf,do_size,src_first,dst_first,size, st); |
913 | 915 |
914 // Check for integer store | 916 // Check for integer store |
915 if( src_first_rc == rc_int && dst_first_rc == rc_stack ) | 917 if( src_first_rc == rc_int && dst_first_rc == rc_stack ) |
916 size = impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_first),src_first,0x89,"MOV ",size); | 918 size = impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_first),src_first,0x89,"MOV ",size, st); |
917 | 919 |
918 // Check for integer load | 920 // Check for integer load |
919 if( dst_first_rc == rc_int && src_first_rc == rc_stack ) | 921 if( dst_first_rc == rc_int && src_first_rc == rc_stack ) |
920 size = impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_first),dst_first,0x8B,"MOV ",size); | 922 size = impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_first),dst_first,0x8B,"MOV ",size, st); |
921 | 923 |
922 // -------------------------------------- | 924 // -------------------------------------- |
923 // Check for float reg-reg copy | 925 // Check for float reg-reg copy |
924 if( src_first_rc == rc_float && dst_first_rc == rc_float ) { | 926 if( src_first_rc == rc_float && dst_first_rc == rc_float ) { |
925 assert( (src_second_rc == rc_bad && dst_second_rc == rc_bad) || | 927 assert( (src_second_rc == rc_bad && dst_second_rc == rc_bad) || |
949 return size + ((src_first != FPR1L_num) ? 2+2 : 2); | 951 return size + ((src_first != FPR1L_num) ? 2+2 : 2); |
950 } | 952 } |
951 | 953 |
952 // Check for float store | 954 // Check for float store |
953 if( src_first_rc == rc_float && dst_first_rc == rc_stack ) { | 955 if( src_first_rc == rc_float && dst_first_rc == rc_stack ) { |
954 return impl_fp_store_helper(cbuf,do_size,src_first,src_second,dst_first,dst_second,ra_->reg2offset(dst_first),size); | 956 return impl_fp_store_helper(cbuf,do_size,src_first,src_second,dst_first,dst_second,ra_->reg2offset(dst_first),size, st); |
955 } | 957 } |
956 | 958 |
957 // Check for float load | 959 // Check for float load |
958 if( dst_first_rc == rc_float && src_first_rc == rc_stack ) { | 960 if( dst_first_rc == rc_float && src_first_rc == rc_stack ) { |
959 int offset = ra_->reg2offset(src_first); | 961 int offset = ra_->reg2offset(src_first); |
985 // Check for xmm reg-reg copy | 987 // Check for xmm reg-reg copy |
986 if( src_first_rc == rc_xmm && dst_first_rc == rc_xmm ) { | 988 if( src_first_rc == rc_xmm && dst_first_rc == rc_xmm ) { |
987 assert( (src_second_rc == rc_bad && dst_second_rc == rc_bad) || | 989 assert( (src_second_rc == rc_bad && dst_second_rc == rc_bad) || |
988 (src_first+1 == src_second && dst_first+1 == dst_second), | 990 (src_first+1 == src_second && dst_first+1 == dst_second), |
989 "no non-adjacent float-moves" ); | 991 "no non-adjacent float-moves" ); |
990 return impl_movx_helper(cbuf,do_size,src_first,dst_first,src_second, dst_second, size); | 992 return impl_movx_helper(cbuf,do_size,src_first,dst_first,src_second, dst_second, size, st); |
991 } | 993 } |
992 | 994 |
993 // Check for xmm store | 995 // Check for xmm store |
994 if( src_first_rc == rc_xmm && dst_first_rc == rc_stack ) { | 996 if( src_first_rc == rc_xmm && dst_first_rc == rc_stack ) { |
995 return impl_x_helper(cbuf,do_size,false,ra_->reg2offset(dst_first),src_first, src_second, size); | 997 return impl_x_helper(cbuf,do_size,false,ra_->reg2offset(dst_first),src_first, src_second, size, st); |
996 } | 998 } |
997 | 999 |
998 // Check for float xmm load | 1000 // Check for float xmm load |
999 if( dst_first_rc == rc_xmm && src_first_rc == rc_stack ) { | 1001 if( dst_first_rc == rc_xmm && src_first_rc == rc_stack ) { |
1000 return impl_x_helper(cbuf,do_size,true ,ra_->reg2offset(src_first),dst_first, dst_second, size); | 1002 return impl_x_helper(cbuf,do_size,true ,ra_->reg2offset(src_first),dst_first, dst_second, size, st); |
1001 } | 1003 } |
1002 | 1004 |
1003 // Copy from float reg to xmm reg | 1005 // Copy from float reg to xmm reg |
1004 if( dst_first_rc == rc_xmm && src_first_rc == rc_float ) { | 1006 if( dst_first_rc == rc_xmm && src_first_rc == rc_float ) { |
1005 // copy to the top of stack from floating point reg | 1007 // copy to the top of stack from floating point reg |
1015 st->print("LEA ESP,[ESP-8]"); | 1017 st->print("LEA ESP,[ESP-8]"); |
1016 #endif | 1018 #endif |
1017 } | 1019 } |
1018 size += 4; | 1020 size += 4; |
1019 | 1021 |
1020 size = impl_fp_store_helper(cbuf,do_size,src_first,src_second,dst_first,dst_second,0,size); | 1022 size = impl_fp_store_helper(cbuf,do_size,src_first,src_second,dst_first,dst_second,0,size, st); |
1021 | 1023 |
1022 // Copy from the temp memory to the xmm reg. | 1024 // Copy from the temp memory to the xmm reg. |
1023 size = impl_x_helper(cbuf,do_size,true ,0,dst_first, dst_second, size); | 1025 size = impl_x_helper(cbuf,do_size,true ,0,dst_first, dst_second, size, st); |
1024 | 1026 |
1025 if( cbuf ) { | 1027 if( cbuf ) { |
1026 emit_opcode(*cbuf,0x8D); // LEA ESP,[ESP+8] | 1028 emit_opcode(*cbuf,0x8D); // LEA ESP,[ESP+8] |
1027 emit_rm(*cbuf, 0x1, ESP_enc, 0x04); | 1029 emit_rm(*cbuf, 0x1, ESP_enc, 0x04); |
1028 emit_rm(*cbuf, 0x0, 0x04, ESP_enc); | 1030 emit_rm(*cbuf, 0x0, 0x04, ESP_enc); |
1045 return size; // Self copy; no move | 1047 return size; // Self copy; no move |
1046 assert( src_second_rc != rc_bad && dst_second_rc != rc_bad, "src_second & dst_second cannot be Bad" ); | 1048 assert( src_second_rc != rc_bad && dst_second_rc != rc_bad, "src_second & dst_second cannot be Bad" ); |
1047 | 1049 |
1048 // Check for second word int-int move | 1050 // Check for second word int-int move |
1049 if( src_second_rc == rc_int && dst_second_rc == rc_int ) | 1051 if( src_second_rc == rc_int && dst_second_rc == rc_int ) |
1050 return impl_mov_helper(cbuf,do_size,src_second,dst_second,size); | 1052 return impl_mov_helper(cbuf,do_size,src_second,dst_second,size, st); |
1051 | 1053 |
1052 // Check for second word integer store | 1054 // Check for second word integer store |
1053 if( src_second_rc == rc_int && dst_second_rc == rc_stack ) | 1055 if( src_second_rc == rc_int && dst_second_rc == rc_stack ) |
1054 return impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_second),src_second,0x89,"MOV ",size); | 1056 return impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_second),src_second,0x89,"MOV ",size, st); |
1055 | 1057 |
1056 // Check for second word integer load | 1058 // Check for second word integer load |
1057 if( dst_second_rc == rc_int && src_second_rc == rc_stack ) | 1059 if( dst_second_rc == rc_int && src_second_rc == rc_stack ) |
1058 return impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_second),dst_second,0x8B,"MOV ",size); | 1060 return impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_second),dst_second,0x8B,"MOV ",size, st); |
1059 | 1061 |
1060 | 1062 |
1061 Unimplemented(); | 1063 Unimplemented(); |
1062 } | 1064 } |
1063 | 1065 |
1316 | 1318 |
1317 // Is this branch offset short enough that a short branch can be used? | 1319 // Is this branch offset short enough that a short branch can be used? |
1318 // | 1320 // |
1319 // NOTE: If the platform does not provide any short branch variants, then | 1321 // NOTE: If the platform does not provide any short branch variants, then |
1320 // this method should return false for offset 0. | 1322 // this method should return false for offset 0. |
1321 bool Matcher::is_short_branch_offset(int offset) { | 1323 bool Matcher::is_short_branch_offset(int rule, int offset) { |
1324 // the short version of jmpConUCF2 contains multiple branches, | |
1325 // making the reach slightly less | |
1326 if (rule == jmpConUCF2_rule) | |
1327 return (-126 <= offset && offset <= 125); | |
1322 return (-128 <= offset && offset <= 127); | 1328 return (-128 <= offset && offset <= 127); |
1323 } | 1329 } |
1324 | 1330 |
1325 const bool Matcher::isSimpleConstant64(jlong value) { | 1331 const bool Matcher::isSimpleConstant64(jlong value) { |
1326 // Will one (StoreL ConL) be cheaper than two (StoreI ConI)?. | 1332 // Will one (StoreL ConL) be cheaper than two (StoreI ConI)?. |
5270 | 5276 |
5271 format %{ "EFLAGS_U" %} | 5277 format %{ "EFLAGS_U" %} |
5272 interface(REG_INTER); | 5278 interface(REG_INTER); |
5273 %} | 5279 %} |
5274 | 5280 |
5281 operand eFlagsRegUCF() %{ | |
5282 constraint(ALLOC_IN_RC(int_flags)); | |
5283 match(RegFlags); | |
5284 predicate(false); | |
5285 | |
5286 format %{ "EFLAGS_U_CF" %} | |
5287 interface(REG_INTER); | |
5288 %} | |
5289 | |
5275 // Condition Code Register used by long compare | 5290 // Condition Code Register used by long compare |
5276 operand flagsReg_long_LTGE() %{ | 5291 operand flagsReg_long_LTGE() %{ |
5277 constraint(ALLOC_IN_RC(int_flags)); | 5292 constraint(ALLOC_IN_RC(int_flags)); |
5278 match(RegFlags); | 5293 match(RegFlags); |
5279 format %{ "FLAGS_LTGE" %} | 5294 format %{ "FLAGS_LTGE" %} |
5747 operand cmpOp() %{ | 5762 operand cmpOp() %{ |
5748 match(Bool); | 5763 match(Bool); |
5749 | 5764 |
5750 format %{ "" %} | 5765 format %{ "" %} |
5751 interface(COND_INTER) %{ | 5766 interface(COND_INTER) %{ |
5752 equal(0x4); | 5767 equal(0x4, "e"); |
5753 not_equal(0x5); | 5768 not_equal(0x5, "ne"); |
5754 less(0xC); | 5769 less(0xC, "l"); |
5755 greater_equal(0xD); | 5770 greater_equal(0xD, "ge"); |
5756 less_equal(0xE); | 5771 less_equal(0xE, "le"); |
5757 greater(0xF); | 5772 greater(0xF, "g"); |
5758 %} | 5773 %} |
5759 %} | 5774 %} |
5760 | 5775 |
5761 // Comparison Code, unsigned compare. Used by FP also, with | 5776 // Comparison Code, unsigned compare. Used by FP also, with |
5762 // C2 (unordered) turned into GT or LT already. The other bits | 5777 // C2 (unordered) turned into GT or LT already. The other bits |
5764 operand cmpOpU() %{ | 5779 operand cmpOpU() %{ |
5765 match(Bool); | 5780 match(Bool); |
5766 | 5781 |
5767 format %{ "" %} | 5782 format %{ "" %} |
5768 interface(COND_INTER) %{ | 5783 interface(COND_INTER) %{ |
5769 equal(0x4); | 5784 equal(0x4, "e"); |
5770 not_equal(0x5); | 5785 not_equal(0x5, "ne"); |
5771 less(0x2); | 5786 less(0x2, "b"); |
5772 greater_equal(0x3); | 5787 greater_equal(0x3, "nb"); |
5773 less_equal(0x6); | 5788 less_equal(0x6, "be"); |
5774 greater(0x7); | 5789 greater(0x7, "nbe"); |
5790 %} | |
5791 %} | |
5792 | |
5793 // Floating comparisons that don't require any fixup for the unordered case | |
5794 operand cmpOpUCF() %{ | |
5795 match(Bool); | |
5796 predicate(n->as_Bool()->_test._test == BoolTest::lt || | |
5797 n->as_Bool()->_test._test == BoolTest::ge || | |
5798 n->as_Bool()->_test._test == BoolTest::le || | |
5799 n->as_Bool()->_test._test == BoolTest::gt); | |
5800 format %{ "" %} | |
5801 interface(COND_INTER) %{ | |
5802 equal(0x4, "e"); | |
5803 not_equal(0x5, "ne"); | |
5804 less(0x2, "b"); | |
5805 greater_equal(0x3, "nb"); | |
5806 less_equal(0x6, "be"); | |
5807 greater(0x7, "nbe"); | |
5808 %} | |
5809 %} | |
5810 | |
5811 | |
5812 // Floating comparisons that can be fixed up with extra conditional jumps | |
5813 operand cmpOpUCF2() %{ | |
5814 match(Bool); | |
5815 predicate(n->as_Bool()->_test._test == BoolTest::ne || | |
5816 n->as_Bool()->_test._test == BoolTest::eq); | |
5817 format %{ "" %} | |
5818 interface(COND_INTER) %{ | |
5819 equal(0x4, "e"); | |
5820 not_equal(0x5, "ne"); | |
5821 less(0x2, "b"); | |
5822 greater_equal(0x3, "nb"); | |
5823 less_equal(0x6, "be"); | |
5824 greater(0x7, "nbe"); | |
5775 %} | 5825 %} |
5776 %} | 5826 %} |
5777 | 5827 |
5778 // Comparison Code for FP conditional move | 5828 // Comparison Code for FP conditional move |
5779 operand cmpOp_fcmov() %{ | 5829 operand cmpOp_fcmov() %{ |
5794 operand cmpOp_commute() %{ | 5844 operand cmpOp_commute() %{ |
5795 match(Bool); | 5845 match(Bool); |
5796 | 5846 |
5797 format %{ "" %} | 5847 format %{ "" %} |
5798 interface(COND_INTER) %{ | 5848 interface(COND_INTER) %{ |
5799 equal(0x4); | 5849 equal(0x4, "e"); |
5800 not_equal(0x5); | 5850 not_equal(0x5, "ne"); |
5801 less(0xF); | 5851 less(0xF, "g"); |
5802 greater_equal(0xE); | 5852 greater_equal(0xE, "le"); |
5803 less_equal(0xD); | 5853 less_equal(0xD, "ge"); |
5804 greater(0xC); | 5854 greater(0xC, "l"); |
5805 %} | 5855 %} |
5806 %} | 5856 %} |
5807 | 5857 |
5808 //----------OPERAND CLASSES---------------------------------------------------- | 5858 //----------OPERAND CLASSES---------------------------------------------------- |
5809 // Operand Classes are groups of operands that are used as to simplify | 5859 // Operand Classes are groups of operands that are used as to simplify |
7355 opcode(0x0F,0x40); | 7405 opcode(0x0F,0x40); |
7356 ins_encode( enc_cmov(cop), RegReg( dst, src ) ); | 7406 ins_encode( enc_cmov(cop), RegReg( dst, src ) ); |
7357 ins_pipe( pipe_cmov_reg ); | 7407 ins_pipe( pipe_cmov_reg ); |
7358 %} | 7408 %} |
7359 | 7409 |
7360 instruct cmovI_regU( eRegI dst, eRegI src, eFlagsRegU cr, cmpOpU cop ) %{ | 7410 instruct cmovI_regU( cmpOpU cop, eFlagsRegU cr, eRegI dst, eRegI src ) %{ |
7361 predicate(VM_Version::supports_cmov() ); | 7411 predicate(VM_Version::supports_cmov() ); |
7362 match(Set dst (CMoveI (Binary cop cr) (Binary dst src))); | 7412 match(Set dst (CMoveI (Binary cop cr) (Binary dst src))); |
7363 ins_cost(200); | 7413 ins_cost(200); |
7364 format %{ "CMOV$cop $dst,$src" %} | 7414 format %{ "CMOV$cop $dst,$src" %} |
7365 opcode(0x0F,0x40); | 7415 opcode(0x0F,0x40); |
7366 ins_encode( enc_cmov(cop), RegReg( dst, src ) ); | 7416 ins_encode( enc_cmov(cop), RegReg( dst, src ) ); |
7367 ins_pipe( pipe_cmov_reg ); | 7417 ins_pipe( pipe_cmov_reg ); |
7418 %} | |
7419 | |
7420 instruct cmovI_regUCF( cmpOpUCF cop, eFlagsRegUCF cr, eRegI dst, eRegI src ) %{ | |
7421 predicate(VM_Version::supports_cmov() ); | |
7422 match(Set dst (CMoveI (Binary cop cr) (Binary dst src))); | |
7423 ins_cost(200); | |
7424 expand %{ | |
7425 cmovI_regU(cop, cr, dst, src); | |
7426 %} | |
7368 %} | 7427 %} |
7369 | 7428 |
7370 // Conditional move | 7429 // Conditional move |
7371 instruct cmovI_mem(cmpOp cop, eFlagsReg cr, eRegI dst, memory src) %{ | 7430 instruct cmovI_mem(cmpOp cop, eFlagsReg cr, eRegI dst, memory src) %{ |
7372 predicate(VM_Version::supports_cmov() ); | 7431 predicate(VM_Version::supports_cmov() ); |
7377 ins_encode( enc_cmov(cop), RegMem( dst, src ) ); | 7436 ins_encode( enc_cmov(cop), RegMem( dst, src ) ); |
7378 ins_pipe( pipe_cmov_mem ); | 7437 ins_pipe( pipe_cmov_mem ); |
7379 %} | 7438 %} |
7380 | 7439 |
7381 // Conditional move | 7440 // Conditional move |
7382 instruct cmovI_memu(cmpOpU cop, eFlagsRegU cr, eRegI dst, memory src) %{ | 7441 instruct cmovI_memU(cmpOpU cop, eFlagsRegU cr, eRegI dst, memory src) %{ |
7383 predicate(VM_Version::supports_cmov() ); | 7442 predicate(VM_Version::supports_cmov() ); |
7384 match(Set dst (CMoveI (Binary cop cr) (Binary dst (LoadI src)))); | 7443 match(Set dst (CMoveI (Binary cop cr) (Binary dst (LoadI src)))); |
7385 ins_cost(250); | 7444 ins_cost(250); |
7386 format %{ "CMOV$cop $dst,$src" %} | 7445 format %{ "CMOV$cop $dst,$src" %} |
7387 opcode(0x0F,0x40); | 7446 opcode(0x0F,0x40); |
7388 ins_encode( enc_cmov(cop), RegMem( dst, src ) ); | 7447 ins_encode( enc_cmov(cop), RegMem( dst, src ) ); |
7389 ins_pipe( pipe_cmov_mem ); | 7448 ins_pipe( pipe_cmov_mem ); |
7449 %} | |
7450 | |
7451 instruct cmovI_memUCF(cmpOpUCF cop, eFlagsRegUCF cr, eRegI dst, memory src) %{ | |
7452 predicate(VM_Version::supports_cmov() ); | |
7453 match(Set dst (CMoveI (Binary cop cr) (Binary dst (LoadI src)))); | |
7454 ins_cost(250); | |
7455 expand %{ | |
7456 cmovI_memU(cop, cr, dst, src); | |
7457 %} | |
7390 %} | 7458 %} |
7391 | 7459 |
7392 // Conditional move | 7460 // Conditional move |
7393 instruct cmovP_reg(eRegP dst, eRegP src, eFlagsReg cr, cmpOp cop ) %{ | 7461 instruct cmovP_reg(eRegP dst, eRegP src, eFlagsReg cr, cmpOp cop ) %{ |
7394 predicate(VM_Version::supports_cmov() ); | 7462 predicate(VM_Version::supports_cmov() ); |
7414 ins_encode( enc_cmov_branch(cop, 0x2), OpcP, RegReg(dst, src)); | 7482 ins_encode( enc_cmov_branch(cop, 0x2), OpcP, RegReg(dst, src)); |
7415 ins_pipe( pipe_cmov_reg ); | 7483 ins_pipe( pipe_cmov_reg ); |
7416 %} | 7484 %} |
7417 | 7485 |
7418 // Conditional move | 7486 // Conditional move |
7419 instruct cmovP_regU(eRegP dst, eRegP src, eFlagsRegU cr, cmpOpU cop ) %{ | 7487 instruct cmovP_regU(cmpOpU cop, eFlagsRegU cr, eRegP dst, eRegP src ) %{ |
7420 predicate(VM_Version::supports_cmov() ); | 7488 predicate(VM_Version::supports_cmov() ); |
7421 match(Set dst (CMoveP (Binary cop cr) (Binary dst src))); | 7489 match(Set dst (CMoveP (Binary cop cr) (Binary dst src))); |
7422 ins_cost(200); | 7490 ins_cost(200); |
7423 format %{ "CMOV$cop $dst,$src\t# ptr" %} | 7491 format %{ "CMOV$cop $dst,$src\t# ptr" %} |
7424 opcode(0x0F,0x40); | 7492 opcode(0x0F,0x40); |
7425 ins_encode( enc_cmov(cop), RegReg( dst, src ) ); | 7493 ins_encode( enc_cmov(cop), RegReg( dst, src ) ); |
7426 ins_pipe( pipe_cmov_reg ); | 7494 ins_pipe( pipe_cmov_reg ); |
7495 %} | |
7496 | |
7497 instruct cmovP_regUCF(cmpOpUCF cop, eFlagsRegUCF cr, eRegP dst, eRegP src ) %{ | |
7498 predicate(VM_Version::supports_cmov() ); | |
7499 match(Set dst (CMoveP (Binary cop cr) (Binary dst src))); | |
7500 ins_cost(200); | |
7501 expand %{ | |
7502 cmovP_regU(cop, cr, dst, src); | |
7503 %} | |
7427 %} | 7504 %} |
7428 | 7505 |
7429 // DISABLED: Requires the ADLC to emit a bottom_type call that | 7506 // DISABLED: Requires the ADLC to emit a bottom_type call that |
7430 // correctly meets the two pointer arguments; one is an incoming | 7507 // correctly meets the two pointer arguments; one is an incoming |
7431 // register but the other is a memory operand. ALSO appears to | 7508 // register but the other is a memory operand. ALSO appears to |
7553 __ bind(skip); | 7630 __ bind(skip); |
7554 %} | 7631 %} |
7555 ins_pipe( pipe_slow ); | 7632 ins_pipe( pipe_slow ); |
7556 %} | 7633 %} |
7557 | 7634 |
7635 instruct fcmovX_regUCF(cmpOpUCF cop, eFlagsRegUCF cr, regX dst, regX src) %{ | |
7636 predicate (UseSSE>=1); | |
7637 match(Set dst (CMoveF (Binary cop cr) (Binary dst src))); | |
7638 ins_cost(200); | |
7639 expand %{ | |
7640 fcmovX_regU(cop, cr, dst, src); | |
7641 %} | |
7642 %} | |
7643 | |
7558 // unsigned version | 7644 // unsigned version |
7559 instruct fcmovXD_regU(cmpOpU cop, eFlagsRegU cr, regXD dst, regXD src) %{ | 7645 instruct fcmovXD_regU(cmpOpU cop, eFlagsRegU cr, regXD dst, regXD src) %{ |
7560 predicate (UseSSE>=2); | 7646 predicate (UseSSE>=2); |
7561 match(Set dst (CMoveD (Binary cop cr) (Binary dst src))); | 7647 match(Set dst (CMoveD (Binary cop cr) (Binary dst src))); |
7562 ins_cost(200); | 7648 ins_cost(200); |
7571 __ bind(skip); | 7657 __ bind(skip); |
7572 %} | 7658 %} |
7573 ins_pipe( pipe_slow ); | 7659 ins_pipe( pipe_slow ); |
7574 %} | 7660 %} |
7575 | 7661 |
7662 instruct fcmovXD_regUCF(cmpOpUCF cop, eFlagsRegUCF cr, regXD dst, regXD src) %{ | |
7663 predicate (UseSSE>=2); | |
7664 match(Set dst (CMoveD (Binary cop cr) (Binary dst src))); | |
7665 ins_cost(200); | |
7666 expand %{ | |
7667 fcmovXD_regU(cop, cr, dst, src); | |
7668 %} | |
7669 %} | |
7670 | |
7576 instruct cmovL_reg(cmpOp cop, eFlagsReg cr, eRegL dst, eRegL src) %{ | 7671 instruct cmovL_reg(cmpOp cop, eFlagsReg cr, eRegL dst, eRegL src) %{ |
7577 predicate(VM_Version::supports_cmov() ); | 7672 predicate(VM_Version::supports_cmov() ); |
7578 match(Set dst (CMoveL (Binary cop cr) (Binary dst src))); | 7673 match(Set dst (CMoveL (Binary cop cr) (Binary dst src))); |
7579 ins_cost(200); | 7674 ins_cost(200); |
7580 format %{ "CMOV$cop $dst.lo,$src.lo\n\t" | 7675 format %{ "CMOV$cop $dst.lo,$src.lo\n\t" |
7591 format %{ "CMOV$cop $dst.lo,$src.lo\n\t" | 7686 format %{ "CMOV$cop $dst.lo,$src.lo\n\t" |
7592 "CMOV$cop $dst.hi,$src.hi" %} | 7687 "CMOV$cop $dst.hi,$src.hi" %} |
7593 opcode(0x0F,0x40); | 7688 opcode(0x0F,0x40); |
7594 ins_encode( enc_cmov(cop), RegReg_Lo2( dst, src ), enc_cmov(cop), RegReg_Hi2( dst, src ) ); | 7689 ins_encode( enc_cmov(cop), RegReg_Lo2( dst, src ), enc_cmov(cop), RegReg_Hi2( dst, src ) ); |
7595 ins_pipe( pipe_cmov_reg_long ); | 7690 ins_pipe( pipe_cmov_reg_long ); |
7691 %} | |
7692 | |
7693 instruct cmovL_regUCF(cmpOpUCF cop, eFlagsRegUCF cr, eRegL dst, eRegL src) %{ | |
7694 predicate(VM_Version::supports_cmov() ); | |
7695 match(Set dst (CMoveL (Binary cop cr) (Binary dst src))); | |
7696 ins_cost(200); | |
7697 expand %{ | |
7698 cmovL_regU(cop, cr, dst, src); | |
7699 %} | |
7596 %} | 7700 %} |
7597 | 7701 |
7598 //----------Arithmetic Instructions-------------------------------------------- | 7702 //----------Arithmetic Instructions-------------------------------------------- |
7599 //----------Addition Instructions---------------------------------------------- | 7703 //----------Addition Instructions---------------------------------------------- |
7600 // Integer Addition Instructions | 7704 // Integer Addition Instructions |
9198 OpcP, RegOpc(src2), | 9302 OpcP, RegOpc(src2), |
9199 cmpF_P6_fixup ); | 9303 cmpF_P6_fixup ); |
9200 ins_pipe( pipe_slow ); | 9304 ins_pipe( pipe_slow ); |
9201 %} | 9305 %} |
9202 | 9306 |
9307 instruct cmpD_cc_P6CF(eFlagsRegUCF cr, regD src1, regD src2) %{ | |
9308 predicate(VM_Version::supports_cmov() && UseSSE <=1); | |
9309 match(Set cr (CmpD src1 src2)); | |
9310 ins_cost(150); | |
9311 format %{ "FLD $src1\n\t" | |
9312 "FUCOMIP ST,$src2 // P6 instruction" %} | |
9313 opcode(0xDF, 0x05); /* DF E8+i or DF /5 */ | |
9314 ins_encode( Push_Reg_D(src1), | |
9315 OpcP, RegOpc(src2)); | |
9316 ins_pipe( pipe_slow ); | |
9317 %} | |
9318 | |
9203 // Compare & branch | 9319 // Compare & branch |
9204 instruct cmpD_cc(eFlagsRegU cr, regD src1, regD src2, eAXRegI rax) %{ | 9320 instruct cmpD_cc(eFlagsRegU cr, regD src1, regD src2, eAXRegI rax) %{ |
9205 predicate(UseSSE<=1); | 9321 predicate(UseSSE<=1); |
9206 match(Set cr (CmpD src1 src2)); | 9322 match(Set cr (CmpD src1 src2)); |
9207 effect(KILL rax); | 9323 effect(KILL rax); |
9262 opcode(0x66, 0x0F, 0x2F); | 9378 opcode(0x66, 0x0F, 0x2F); |
9263 ins_encode(OpcP, OpcS, Opcode(tertiary), RegReg(dst, src), cmpF_P6_fixup); | 9379 ins_encode(OpcP, OpcS, Opcode(tertiary), RegReg(dst, src), cmpF_P6_fixup); |
9264 ins_pipe( pipe_slow ); | 9380 ins_pipe( pipe_slow ); |
9265 %} | 9381 %} |
9266 | 9382 |
9383 instruct cmpXD_ccCF(eFlagsRegUCF cr, regXD dst, regXD src) %{ | |
9384 predicate(UseSSE>=2); | |
9385 match(Set cr (CmpD dst src)); | |
9386 ins_cost(100); | |
9387 format %{ "COMISD $dst,$src" %} | |
9388 opcode(0x66, 0x0F, 0x2F); | |
9389 ins_encode(OpcP, OpcS, Opcode(tertiary), RegReg(dst, src)); | |
9390 ins_pipe( pipe_slow ); | |
9391 %} | |
9392 | |
9267 // float compare and set condition codes in EFLAGS by XMM regs | 9393 // float compare and set condition codes in EFLAGS by XMM regs |
9268 instruct cmpXD_ccmem(eFlagsRegU cr, regXD dst, memory src, eAXRegI rax) %{ | 9394 instruct cmpXD_ccmem(eFlagsRegU cr, regXD dst, memory src, eAXRegI rax) %{ |
9269 predicate(UseSSE>=2); | 9395 predicate(UseSSE>=2); |
9270 match(Set cr (CmpD dst (LoadD src))); | 9396 match(Set cr (CmpD dst (LoadD src))); |
9271 effect(KILL rax); | 9397 effect(KILL rax); |
9275 "\tMOV ah,1 // saw a NaN, set CF\n" | 9401 "\tMOV ah,1 // saw a NaN, set CF\n" |
9276 "\tSAHF\n" | 9402 "\tSAHF\n" |
9277 "exit:\tNOP // avoid branch to branch" %} | 9403 "exit:\tNOP // avoid branch to branch" %} |
9278 opcode(0x66, 0x0F, 0x2F); | 9404 opcode(0x66, 0x0F, 0x2F); |
9279 ins_encode(OpcP, OpcS, Opcode(tertiary), RegMem(dst, src), cmpF_P6_fixup); | 9405 ins_encode(OpcP, OpcS, Opcode(tertiary), RegMem(dst, src), cmpF_P6_fixup); |
9406 ins_pipe( pipe_slow ); | |
9407 %} | |
9408 | |
9409 instruct cmpXD_ccmemCF(eFlagsRegUCF cr, regXD dst, memory src) %{ | |
9410 predicate(UseSSE>=2); | |
9411 match(Set cr (CmpD dst (LoadD src))); | |
9412 ins_cost(100); | |
9413 format %{ "COMISD $dst,$src" %} | |
9414 opcode(0x66, 0x0F, 0x2F); | |
9415 ins_encode(OpcP, OpcS, Opcode(tertiary), RegMem(dst, src)); | |
9280 ins_pipe( pipe_slow ); | 9416 ins_pipe( pipe_slow ); |
9281 %} | 9417 %} |
9282 | 9418 |
9283 // Compare into -1,0,1 in XMM | 9419 // Compare into -1,0,1 in XMM |
9284 instruct cmpXD_reg(eRegI dst, regXD src1, regXD src2, eFlagsReg cr) %{ | 9420 instruct cmpXD_reg(eRegI dst, regXD src1, regXD src2, eFlagsReg cr) %{ |
10165 OpcP, RegOpc(src2), | 10301 OpcP, RegOpc(src2), |
10166 cmpF_P6_fixup ); | 10302 cmpF_P6_fixup ); |
10167 ins_pipe( pipe_slow ); | 10303 ins_pipe( pipe_slow ); |
10168 %} | 10304 %} |
10169 | 10305 |
10306 instruct cmpF_cc_P6CF(eFlagsRegUCF cr, regF src1, regF src2) %{ | |
10307 predicate(VM_Version::supports_cmov() && UseSSE == 0); | |
10308 match(Set cr (CmpF src1 src2)); | |
10309 ins_cost(100); | |
10310 format %{ "FLD $src1\n\t" | |
10311 "FUCOMIP ST,$src2 // P6 instruction" %} | |
10312 opcode(0xDF, 0x05); /* DF E8+i or DF /5 */ | |
10313 ins_encode( Push_Reg_D(src1), | |
10314 OpcP, RegOpc(src2)); | |
10315 ins_pipe( pipe_slow ); | |
10316 %} | |
10317 | |
10170 | 10318 |
10171 // Compare & branch | 10319 // Compare & branch |
10172 instruct cmpF_cc(eFlagsRegU cr, regF src1, regF src2, eAXRegI rax) %{ | 10320 instruct cmpF_cc(eFlagsRegU cr, regF src1, regF src2, eAXRegI rax) %{ |
10173 predicate(UseSSE == 0); | 10321 predicate(UseSSE == 0); |
10174 match(Set cr (CmpF src1 src2)); | 10322 match(Set cr (CmpF src1 src2)); |
10230 opcode(0x0F, 0x2F); | 10378 opcode(0x0F, 0x2F); |
10231 ins_encode(OpcP, OpcS, RegReg(dst, src), cmpF_P6_fixup); | 10379 ins_encode(OpcP, OpcS, RegReg(dst, src), cmpF_P6_fixup); |
10232 ins_pipe( pipe_slow ); | 10380 ins_pipe( pipe_slow ); |
10233 %} | 10381 %} |
10234 | 10382 |
10383 instruct cmpX_ccCF(eFlagsRegUCF cr, regX dst, regX src) %{ | |
10384 predicate(UseSSE>=1); | |
10385 match(Set cr (CmpF dst src)); | |
10386 ins_cost(100); | |
10387 format %{ "COMISS $dst,$src" %} | |
10388 opcode(0x0F, 0x2F); | |
10389 ins_encode(OpcP, OpcS, RegReg(dst, src)); | |
10390 ins_pipe( pipe_slow ); | |
10391 %} | |
10392 | |
10235 // float compare and set condition codes in EFLAGS by XMM regs | 10393 // float compare and set condition codes in EFLAGS by XMM regs |
10236 instruct cmpX_ccmem(eFlagsRegU cr, regX dst, memory src, eAXRegI rax) %{ | 10394 instruct cmpX_ccmem(eFlagsRegU cr, regX dst, memory src, eAXRegI rax) %{ |
10237 predicate(UseSSE>=1); | 10395 predicate(UseSSE>=1); |
10238 match(Set cr (CmpF dst (LoadF src))); | 10396 match(Set cr (CmpF dst (LoadF src))); |
10239 effect(KILL rax); | 10397 effect(KILL rax); |
10243 "\tMOV ah,1 // saw a NaN, set CF\n" | 10401 "\tMOV ah,1 // saw a NaN, set CF\n" |
10244 "\tSAHF\n" | 10402 "\tSAHF\n" |
10245 "exit:\tNOP // avoid branch to branch" %} | 10403 "exit:\tNOP // avoid branch to branch" %} |
10246 opcode(0x0F, 0x2F); | 10404 opcode(0x0F, 0x2F); |
10247 ins_encode(OpcP, OpcS, RegMem(dst, src), cmpF_P6_fixup); | 10405 ins_encode(OpcP, OpcS, RegMem(dst, src), cmpF_P6_fixup); |
10406 ins_pipe( pipe_slow ); | |
10407 %} | |
10408 | |
10409 instruct cmpX_ccmemCF(eFlagsRegUCF cr, regX dst, memory src) %{ | |
10410 predicate(UseSSE>=1); | |
10411 match(Set cr (CmpF dst (LoadF src))); | |
10412 ins_cost(100); | |
10413 format %{ "COMISS $dst,$src" %} | |
10414 opcode(0x0F, 0x2F); | |
10415 ins_encode(OpcP, OpcS, RegMem(dst, src)); | |
10248 ins_pipe( pipe_slow ); | 10416 ins_pipe( pipe_slow ); |
10249 %} | 10417 %} |
10250 | 10418 |
10251 // Compare into -1,0,1 in XMM | 10419 // Compare into -1,0,1 in XMM |
10252 instruct cmpX_reg(eRegI dst, regX src1, regX src2, eFlagsReg cr) %{ | 10420 instruct cmpX_reg(eRegI dst, regX src1, regX src2, eFlagsReg cr) %{ |
12097 ins_encode( Jcc( cop, labl) ); | 12265 ins_encode( Jcc( cop, labl) ); |
12098 ins_pipe( pipe_jcc ); | 12266 ins_pipe( pipe_jcc ); |
12099 ins_pc_relative(1); | 12267 ins_pc_relative(1); |
12100 %} | 12268 %} |
12101 | 12269 |
12270 instruct jmpLoopEndUCF(cmpOpUCF cop, eFlagsRegUCF cmp, label labl) %{ | |
12271 match(CountedLoopEnd cop cmp); | |
12272 effect(USE labl); | |
12273 | |
12274 ins_cost(200); | |
12275 format %{ "J$cop,u $labl\t# Loop end" %} | |
12276 size(6); | |
12277 opcode(0x0F, 0x80); | |
12278 ins_encode( Jcc( cop, labl) ); | |
12279 ins_pipe( pipe_jcc ); | |
12280 ins_pc_relative(1); | |
12281 %} | |
12282 | |
12102 // Jump Direct Conditional - using unsigned comparison | 12283 // Jump Direct Conditional - using unsigned comparison |
12103 instruct jmpConU(cmpOpU cop, eFlagsRegU cmp, label labl) %{ | 12284 instruct jmpConU(cmpOpU cop, eFlagsRegU cmp, label labl) %{ |
12104 match(If cop cmp); | 12285 match(If cop cmp); |
12105 effect(USE labl); | 12286 effect(USE labl); |
12106 | 12287 |
12107 ins_cost(300); | 12288 ins_cost(300); |
12108 format %{ "J$cop,u $labl" %} | 12289 format %{ "J$cop,u $labl" %} |
12109 size(6); | 12290 size(6); |
12110 opcode(0x0F, 0x80); | 12291 opcode(0x0F, 0x80); |
12111 ins_encode( Jcc( cop, labl) ); | 12292 ins_encode(Jcc(cop, labl)); |
12112 ins_pipe( pipe_jcc ); | 12293 ins_pipe(pipe_jcc); |
12294 ins_pc_relative(1); | |
12295 %} | |
12296 | |
12297 instruct jmpConUCF(cmpOpUCF cop, eFlagsRegUCF cmp, label labl) %{ | |
12298 match(If cop cmp); | |
12299 effect(USE labl); | |
12300 | |
12301 ins_cost(200); | |
12302 format %{ "J$cop,u $labl" %} | |
12303 size(6); | |
12304 opcode(0x0F, 0x80); | |
12305 ins_encode(Jcc(cop, labl)); | |
12306 ins_pipe(pipe_jcc); | |
12307 ins_pc_relative(1); | |
12308 %} | |
12309 | |
12310 instruct jmpConUCF2(cmpOpUCF2 cop, eFlagsRegUCF cmp, label labl) %{ | |
12311 match(If cop cmp); | |
12312 effect(USE labl); | |
12313 | |
12314 ins_cost(200); | |
12315 format %{ $$template | |
12316 if ($cop$$cmpcode == Assembler::notEqual) { | |
12317 $$emit$$"JP,u $labl\n\t" | |
12318 $$emit$$"J$cop,u $labl" | |
12319 } else { | |
12320 $$emit$$"JP,u done\n\t" | |
12321 $$emit$$"J$cop,u $labl\n\t" | |
12322 $$emit$$"done:" | |
12323 } | |
12324 %} | |
12325 size(12); | |
12326 opcode(0x0F, 0x80); | |
12327 ins_encode %{ | |
12328 Label* l = $labl$$label; | |
12329 $$$emit8$primary; | |
12330 emit_cc(cbuf, $secondary, Assembler::parity); | |
12331 int parity_disp = -1; | |
12332 bool ok = false; | |
12333 if ($cop$$cmpcode == Assembler::notEqual) { | |
12334 // the two jumps 6 bytes apart so the jump distances are too | |
12335 parity_disp = l ? (l->loc_pos() - (cbuf.code_size() + 4)) : 0; | |
12336 } else if ($cop$$cmpcode == Assembler::equal) { | |
12337 parity_disp = 6; | |
12338 ok = true; | |
12339 } else { | |
12340 ShouldNotReachHere(); | |
12341 } | |
12342 emit_d32(cbuf, parity_disp); | |
12343 $$$emit8$primary; | |
12344 emit_cc(cbuf, $secondary, $cop$$cmpcode); | |
12345 int disp = l ? (l->loc_pos() - (cbuf.code_size() + 4)) : 0; | |
12346 emit_d32(cbuf, disp); | |
12347 %} | |
12348 ins_pipe(pipe_jcc); | |
12113 ins_pc_relative(1); | 12349 ins_pc_relative(1); |
12114 %} | 12350 %} |
12115 | 12351 |
12116 // ============================================================================ | 12352 // ============================================================================ |
12117 // The 2nd slow-half of a subtype check. Scan the subklass's 2ndary superklass | 12353 // The 2nd slow-half of a subtype check. Scan the subklass's 2ndary superklass |
12206 instruct jmpLoopEnd_short(cmpOp cop, eFlagsReg cr, label labl) %{ | 12442 instruct jmpLoopEnd_short(cmpOp cop, eFlagsReg cr, label labl) %{ |
12207 match(CountedLoopEnd cop cr); | 12443 match(CountedLoopEnd cop cr); |
12208 effect(USE labl); | 12444 effect(USE labl); |
12209 | 12445 |
12210 ins_cost(300); | 12446 ins_cost(300); |
12211 format %{ "J$cop,s $labl" %} | 12447 format %{ "J$cop,s $labl\t# Loop end" %} |
12212 size(2); | 12448 size(2); |
12213 opcode(0x70); | 12449 opcode(0x70); |
12214 ins_encode( JccShort( cop, labl) ); | 12450 ins_encode( JccShort( cop, labl) ); |
12215 ins_pipe( pipe_jcc ); | 12451 ins_pipe( pipe_jcc ); |
12216 ins_pc_relative(1); | 12452 ins_pc_relative(1); |
12218 %} | 12454 %} |
12219 | 12455 |
12220 // Jump Direct Conditional - Label defines a relative address from Jcc+1 | 12456 // Jump Direct Conditional - Label defines a relative address from Jcc+1 |
12221 instruct jmpLoopEndU_short(cmpOpU cop, eFlagsRegU cmp, label labl) %{ | 12457 instruct jmpLoopEndU_short(cmpOpU cop, eFlagsRegU cmp, label labl) %{ |
12222 match(CountedLoopEnd cop cmp); | 12458 match(CountedLoopEnd cop cmp); |
12459 effect(USE labl); | |
12460 | |
12461 ins_cost(300); | |
12462 format %{ "J$cop,us $labl\t# Loop end" %} | |
12463 size(2); | |
12464 opcode(0x70); | |
12465 ins_encode( JccShort( cop, labl) ); | |
12466 ins_pipe( pipe_jcc ); | |
12467 ins_pc_relative(1); | |
12468 ins_short_branch(1); | |
12469 %} | |
12470 | |
12471 instruct jmpLoopEndUCF_short(cmpOpUCF cop, eFlagsRegUCF cmp, label labl) %{ | |
12472 match(CountedLoopEnd cop cmp); | |
12473 effect(USE labl); | |
12474 | |
12475 ins_cost(300); | |
12476 format %{ "J$cop,us $labl\t# Loop end" %} | |
12477 size(2); | |
12478 opcode(0x70); | |
12479 ins_encode( JccShort( cop, labl) ); | |
12480 ins_pipe( pipe_jcc ); | |
12481 ins_pc_relative(1); | |
12482 ins_short_branch(1); | |
12483 %} | |
12484 | |
12485 // Jump Direct Conditional - using unsigned comparison | |
12486 instruct jmpConU_short(cmpOpU cop, eFlagsRegU cmp, label labl) %{ | |
12487 match(If cop cmp); | |
12223 effect(USE labl); | 12488 effect(USE labl); |
12224 | 12489 |
12225 ins_cost(300); | 12490 ins_cost(300); |
12226 format %{ "J$cop,us $labl" %} | 12491 format %{ "J$cop,us $labl" %} |
12227 size(2); | 12492 size(2); |
12230 ins_pipe( pipe_jcc ); | 12495 ins_pipe( pipe_jcc ); |
12231 ins_pc_relative(1); | 12496 ins_pc_relative(1); |
12232 ins_short_branch(1); | 12497 ins_short_branch(1); |
12233 %} | 12498 %} |
12234 | 12499 |
12235 // Jump Direct Conditional - using unsigned comparison | 12500 instruct jmpConUCF_short(cmpOpUCF cop, eFlagsRegUCF cmp, label labl) %{ |
12236 instruct jmpConU_short(cmpOpU cop, eFlagsRegU cmp, label labl) %{ | |
12237 match(If cop cmp); | 12501 match(If cop cmp); |
12238 effect(USE labl); | 12502 effect(USE labl); |
12239 | 12503 |
12240 ins_cost(300); | 12504 ins_cost(300); |
12241 format %{ "J$cop,us $labl" %} | 12505 format %{ "J$cop,us $labl" %} |
12242 size(2); | 12506 size(2); |
12243 opcode(0x70); | 12507 opcode(0x70); |
12244 ins_encode( JccShort( cop, labl) ); | 12508 ins_encode( JccShort( cop, labl) ); |
12245 ins_pipe( pipe_jcc ); | 12509 ins_pipe( pipe_jcc ); |
12510 ins_pc_relative(1); | |
12511 ins_short_branch(1); | |
12512 %} | |
12513 | |
12514 instruct jmpConUCF2_short(cmpOpUCF2 cop, eFlagsRegUCF cmp, label labl) %{ | |
12515 match(If cop cmp); | |
12516 effect(USE labl); | |
12517 | |
12518 ins_cost(300); | |
12519 format %{ $$template | |
12520 if ($cop$$cmpcode == Assembler::notEqual) { | |
12521 $$emit$$"JP,u,s $labl\n\t" | |
12522 $$emit$$"J$cop,u,s $labl" | |
12523 } else { | |
12524 $$emit$$"JP,u,s done\n\t" | |
12525 $$emit$$"J$cop,u,s $labl\n\t" | |
12526 $$emit$$"done:" | |
12527 } | |
12528 %} | |
12529 size(4); | |
12530 opcode(0x70); | |
12531 ins_encode %{ | |
12532 Label* l = $labl$$label; | |
12533 emit_cc(cbuf, $primary, Assembler::parity); | |
12534 int parity_disp = -1; | |
12535 if ($cop$$cmpcode == Assembler::notEqual) { | |
12536 parity_disp = l ? (l->loc_pos() - (cbuf.code_size() + 1)) : 0; | |
12537 } else if ($cop$$cmpcode == Assembler::equal) { | |
12538 parity_disp = 2; | |
12539 } else { | |
12540 ShouldNotReachHere(); | |
12541 } | |
12542 emit_d8(cbuf, parity_disp); | |
12543 emit_cc(cbuf, $primary, $cop$$cmpcode); | |
12544 int disp = l ? (l->loc_pos() - (cbuf.code_size() + 1)) : 0; | |
12545 emit_d8(cbuf, disp); | |
12546 assert(-128 <= disp && disp <= 127, "Displacement too large for short jmp"); | |
12547 assert(-128 <= parity_disp && parity_disp <= 127, "Displacement too large for short jmp"); | |
12548 %} | |
12549 ins_pipe(pipe_jcc); | |
12246 ins_pc_relative(1); | 12550 ins_pc_relative(1); |
12247 ins_short_branch(1); | 12551 ins_short_branch(1); |
12248 %} | 12552 %} |
12249 | 12553 |
12250 // ============================================================================ | 12554 // ============================================================================ |