84 // the stack will not have this element so FPR1 == st(0) from the
85 // oopMap viewpoint. This same weirdness with numbering causes
86 // instruction encoding to have to play games with the register
87 // encode to correct for this 0/1 issue. See MachSpillCopyNode::implementation
88 // where it does flt->flt moves to see an example
89 //
90 reg_def FPR1L( SOC, SOC, Op_RegF, 1, as_FloatRegister(0)->as_VMReg());
91 reg_def FPR1H( SOC, SOC, Op_RegF, 1, as_FloatRegister(0)->as_VMReg()->next());
92 reg_def FPR2L( SOC, SOC, Op_RegF, 2, as_FloatRegister(1)->as_VMReg());
93 reg_def FPR2H( SOC, SOC, Op_RegF, 2, as_FloatRegister(1)->as_VMReg()->next());
94 reg_def FPR3L( SOC, SOC, Op_RegF, 3, as_FloatRegister(2)->as_VMReg());
95 reg_def FPR3H( SOC, SOC, Op_RegF, 3, as_FloatRegister(2)->as_VMReg()->next());
96 reg_def FPR4L( SOC, SOC, Op_RegF, 4, as_FloatRegister(3)->as_VMReg());
97 reg_def FPR4H( SOC, SOC, Op_RegF, 4, as_FloatRegister(3)->as_VMReg()->next());
98 reg_def FPR5L( SOC, SOC, Op_RegF, 5, as_FloatRegister(4)->as_VMReg());
99 reg_def FPR5H( SOC, SOC, Op_RegF, 5, as_FloatRegister(4)->as_VMReg()->next());
100 reg_def FPR6L( SOC, SOC, Op_RegF, 6, as_FloatRegister(5)->as_VMReg());
101 reg_def FPR6H( SOC, SOC, Op_RegF, 6, as_FloatRegister(5)->as_VMReg()->next());
102 reg_def FPR7L( SOC, SOC, Op_RegF, 7, as_FloatRegister(6)->as_VMReg());
103 reg_def FPR7H( SOC, SOC, Op_RegF, 7, as_FloatRegister(6)->as_VMReg()->next());
104
105 // Specify priority of register selection within phases of register
106 // allocation. Highest priority is first. A useful heuristic is to
107 // give registers a low priority when they are required by machine
108 // instructions, like EAX and EDX. Registers which are used as
109 // pairs must fall on an even boundary (witness the FPR#L's in this list).
110 // For the Intel integer registers, the equivalent Long pairs are
111 // EDX:EAX, EBX:ECX, and EDI:EBP.
112 alloc_class chunk0( ECX, EBX, EBP, EDI, EAX, EDX, ESI, ESP,
113 FPR0L, FPR0H, FPR1L, FPR1H, FPR2L, FPR2H,
114 FPR3L, FPR3H, FPR4L, FPR4H, FPR5L, FPR5H,
115 FPR6L, FPR6H, FPR7L, FPR7H );
116
117
118 //----------Architecture Description Register Classes--------------------------
119 // Several register classes are automatically defined based upon information in
120 // this architecture description.
121 // 1) reg_class inline_cache_reg ( /* as def'd in frame section */ )
122 // 2) reg_class compiler_method_oop_reg ( /* as def'd in frame section */ )
123 // 2) reg_class interpreter_method_oop_reg ( /* as def'd in frame section */ )
124 // 3) reg_class stack_slots( /* one chunk of stack-based "registers" */ )
125 //
126 // Class for all registers
127 reg_class any_reg(EAX, EDX, EBP, EDI, ESI, ECX, EBX, ESP);
128 // Class for general registers
129 reg_class int_reg(EAX, EDX, EBP, EDI, ESI, ECX, EBX);
130 // Class for general registers which may be used for implicit null checks on win95
131 // Also safe for use by tailjump. We don't want to allocate in rbp,
132 reg_class int_reg_no_rbp(EAX, EDX, EDI, ESI, ECX, EBX);
133 // Class of "X" registers
134 reg_class int_x_reg(EBX, ECX, EDX, EAX);
135 // Class of registers that can appear in an address with no offset.
218 return operand;
219 }
220
221 // Buffer for 128-bits masks used by SSE instructions.
222 static jlong fp_signmask_pool[(4+1)*2]; // 4*128bits(data) + 128bits(alignment)
223
224 // Static initialization during VM startup.
225 static jlong *float_signmask_pool = double_quadword(&fp_signmask_pool[1*2], CONST64(0x7FFFFFFF7FFFFFFF), CONST64(0x7FFFFFFF7FFFFFFF));
226 static jlong *double_signmask_pool = double_quadword(&fp_signmask_pool[2*2], CONST64(0x7FFFFFFFFFFFFFFF), CONST64(0x7FFFFFFFFFFFFFFF));
227 static jlong *float_signflip_pool = double_quadword(&fp_signmask_pool[3*2], CONST64(0x8000000080000000), CONST64(0x8000000080000000));
228 static jlong *double_signflip_pool = double_quadword(&fp_signmask_pool[4*2], CONST64(0x8000000000000000), CONST64(0x8000000000000000));
229
230 // Offset hacking within calls.
231 static int pre_call_resets_size() {
232 int size = 0;
233 Compile* C = Compile::current();
234 if (C->in_24_bit_fp_mode()) {
235 size += 6; // fldcw
236 }
237 if (C->max_vector_size() > 16) {
238 size += 3; // vzeroupper
239 }
240 return size;
241 }
242
243 static int preserve_SP_size() {
244 return 2; // op, rm(reg/reg)
245 }
246
247 // !!!!! Special hack to get all type of calls to specify the byte offset
248 // from the start of the call to the point where the return address
249 // will point.
250 int MachCallStaticJavaNode::ret_addr_offset() {
251 int offset = 5 + pre_call_resets_size(); // 5 bytes from start of call to where return address points
252 if (_method_handle_invoke)
253 offset += preserve_SP_size();
254 return offset;
255 }
256
257 int MachCallDynamicJavaNode::ret_addr_offset() {
258 return 10 + pre_call_resets_size(); // 10 bytes from start of call to where return address points
259 }
714 emit_opcode (*cbuf, opcode );
715 encode_RegMem(*cbuf, Matcher::_regEncode[reg], ESP_enc, 0x4, 0, offset, relocInfo::none);
716 #ifndef PRODUCT
717 } else if( !do_size ) {
718 if( size != 0 ) st->print("\n\t");
719 if( opcode == 0x8B || opcode == 0x89 ) { // MOV
720 if( is_load ) st->print("%s %s,[ESP + #%d]",op_str,Matcher::regName[reg],offset);
721 else st->print("%s [ESP + #%d],%s",op_str,offset,Matcher::regName[reg]);
722 } else { // FLD, FST, PUSH, POP
723 st->print("%s [ESP + #%d]",op_str,offset);
724 }
725 #endif
726 }
727 int offset_size = (offset == 0) ? 0 : ((offset <= 127) ? 1 : 4);
728 return size+3+offset_size;
729 }
730
731 // Helper for XMM registers. Extra opcode bits, limited syntax.
732 static int impl_x_helper( CodeBuffer *cbuf, bool do_size, bool is_load,
733 int offset, int reg_lo, int reg_hi, int size, outputStream* st ) {
734 if (cbuf) {
735 MacroAssembler _masm(cbuf);
736 if (reg_lo+1 == reg_hi) { // double move?
737 if (is_load) {
738 __ movdbl(as_XMMRegister(Matcher::_regEncode[reg_lo]), Address(rsp, offset));
739 } else {
740 __ movdbl(Address(rsp, offset), as_XMMRegister(Matcher::_regEncode[reg_lo]));
741 }
742 } else {
743 if (is_load) {
744 __ movflt(as_XMMRegister(Matcher::_regEncode[reg_lo]), Address(rsp, offset));
745 } else {
746 __ movflt(Address(rsp, offset), as_XMMRegister(Matcher::_regEncode[reg_lo]));
747 }
748 }
749 #ifndef PRODUCT
750 } else if (!do_size) {
751 if (size != 0) st->print("\n\t");
752 if (reg_lo+1 == reg_hi) { // double move?
753 if (is_load) st->print("%s %s,[ESP + #%d]",
754 UseXmmLoadAndClearUpper ? "MOVSD " : "MOVLPD",
755 Matcher::regName[reg_lo], offset);
756 else st->print("MOVSD [ESP + #%d],%s",
757 offset, Matcher::regName[reg_lo]);
758 } else {
759 if (is_load) st->print("MOVSS %s,[ESP + #%d]",
760 Matcher::regName[reg_lo], offset);
761 else st->print("MOVSS [ESP + #%d],%s",
762 offset, Matcher::regName[reg_lo]);
763 }
764 #endif
765 }
766 int offset_size = (offset == 0) ? 0 : ((offset <= 127) ? 1 : 4);
767 // VEX_2bytes prefix is used if UseAVX > 0, so it takes the same 2 bytes as SIMD prefix.
768 return size+5+offset_size;
769 }
770
771
772 static int impl_movx_helper( CodeBuffer *cbuf, bool do_size, int src_lo, int dst_lo,
773 int src_hi, int dst_hi, int size, outputStream* st ) {
774 if (cbuf) {
775 MacroAssembler _masm(cbuf);
776 if (src_lo+1 == src_hi && dst_lo+1 == dst_hi) { // double move?
777 __ movdbl(as_XMMRegister(Matcher::_regEncode[dst_lo]),
778 as_XMMRegister(Matcher::_regEncode[src_lo]));
779 } else {
780 __ movflt(as_XMMRegister(Matcher::_regEncode[dst_lo]),
781 as_XMMRegister(Matcher::_regEncode[src_lo]));
782 }
783 #ifndef PRODUCT
784 } else if (!do_size) {
785 if (size != 0) st->print("\n\t");
786 if (UseXmmRegToRegMoveAll) {//Use movaps,movapd to move between xmm registers
787 if (src_lo+1 == src_hi && dst_lo+1 == dst_hi) { // double move?
788 st->print("MOVAPD %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]);
789 } else {
790 st->print("MOVAPS %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]);
791 }
792 } else {
793 if( src_lo+1 == src_hi && dst_lo+1 == dst_hi ) { // double move?
794 st->print("MOVSD %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]);
795 } else {
796 st->print("MOVSS %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]);
797 }
798 }
799 #endif
800 }
801 // VEX_2bytes prefix is used if UseAVX > 0, and it takes the same 2 bytes as SIMD prefix.
802 // Only MOVAPS SSE prefix uses 1 byte.
803 int sz = 4;
804 if (!(src_lo+1 == src_hi && dst_lo+1 == dst_hi) &&
805 UseXmmRegToRegMoveAll && (UseAVX == 0)) sz = 3;
806 return size + sz;
807 }
808
809 static int impl_movgpr2x_helper( CodeBuffer *cbuf, bool do_size, int src_lo, int dst_lo,
810 int src_hi, int dst_hi, int size, outputStream* st ) {
811 // 32-bit
812 if (cbuf) {
813 MacroAssembler _masm(cbuf);
814 __ movdl(as_XMMRegister(Matcher::_regEncode[dst_lo]),
815 as_Register(Matcher::_regEncode[src_lo]));
816 #ifndef PRODUCT
817 } else if (!do_size) {
818 st->print("movdl %s, %s\t# spill", Matcher::regName[dst_lo], Matcher::regName[src_lo]);
819 #endif
820 }
821 return 4;
822 }
823
824
825 static int impl_movx2gpr_helper( CodeBuffer *cbuf, bool do_size, int src_lo, int dst_lo,
826 int src_hi, int dst_hi, int size, outputStream* st ) {
827 // 32-bit
828 if (cbuf) {
829 MacroAssembler _masm(cbuf);
830 __ movdl(as_Register(Matcher::_regEncode[dst_lo]),
831 as_XMMRegister(Matcher::_regEncode[src_lo]));
832 #ifndef PRODUCT
833 } else if (!do_size) {
834 st->print("movdl %s, %s\t# spill", Matcher::regName[dst_lo], Matcher::regName[src_lo]);
835 #endif
836 }
837 return 4;
838 }
839
840 static int impl_mov_helper( CodeBuffer *cbuf, bool do_size, int src, int dst, int size, outputStream* st ) {
841 if( cbuf ) {
842 emit_opcode(*cbuf, 0x8B );
843 emit_rm (*cbuf, 0x3, Matcher::_regEncode[dst], Matcher::_regEncode[src] );
844 #ifndef PRODUCT
845 } else if( !do_size ) {
846 if( size != 0 ) st->print("\n\t");
847 st->print("MOV %s,%s",Matcher::regName[dst],Matcher::regName[src]);
848 #endif
849 }
850 return size+2;
851 }
852
853 static int impl_fp_store_helper( CodeBuffer *cbuf, bool do_size, int src_lo, int src_hi, int dst_lo, int dst_hi,
854 int offset, int size, outputStream* st ) {
855 if( src_lo != FPR1L_num ) { // Move value to top of FP stack, if not already there
856 if( cbuf ) {
857 emit_opcode( *cbuf, 0xD9 ); // FLD (i.e., push it)
888 int stack_offset, int reg, uint ireg, outputStream* st);
889
890 static int vec_stack_to_stack_helper(CodeBuffer *cbuf, bool do_size, int src_offset,
891 int dst_offset, uint ireg, outputStream* st) {
892 int calc_size = 0;
893 int src_offset_size = (src_offset == 0) ? 0 : ((src_offset < 0x80) ? 1 : 4);
894 int dst_offset_size = (dst_offset == 0) ? 0 : ((dst_offset < 0x80) ? 1 : 4);
895 switch (ireg) {
896 case Op_VecS:
897 calc_size = 3+src_offset_size + 3+dst_offset_size;
898 break;
899 case Op_VecD:
900 calc_size = 3+src_offset_size + 3+dst_offset_size;
901 src_offset += 4;
902 dst_offset += 4;
903 src_offset_size = (src_offset == 0) ? 0 : ((src_offset < 0x80) ? 1 : 4);
904 dst_offset_size = (dst_offset == 0) ? 0 : ((dst_offset < 0x80) ? 1 : 4);
905 calc_size += 3+src_offset_size + 3+dst_offset_size;
906 break;
907 case Op_VecX:
908 calc_size = 6 + 6 + 5+src_offset_size + 5+dst_offset_size;
909 break;
910 case Op_VecY:
911 calc_size = 6 + 6 + 5+src_offset_size + 5+dst_offset_size;
912 break;
913 default:
914 ShouldNotReachHere();
915 }
916 if (cbuf) {
917 MacroAssembler _masm(cbuf);
918 int offset = __ offset();
919 switch (ireg) {
920 case Op_VecS:
921 __ pushl(Address(rsp, src_offset));
922 __ popl (Address(rsp, dst_offset));
923 break;
924 case Op_VecD:
925 __ pushl(Address(rsp, src_offset));
926 __ popl (Address(rsp, dst_offset));
927 __ pushl(Address(rsp, src_offset+4));
928 __ popl (Address(rsp, dst_offset+4));
929 break;
930 case Op_VecX:
931 __ movdqu(Address(rsp, -16), xmm0);
932 __ movdqu(xmm0, Address(rsp, src_offset));
933 __ movdqu(Address(rsp, dst_offset), xmm0);
934 __ movdqu(xmm0, Address(rsp, -16));
935 break;
936 case Op_VecY:
937 __ vmovdqu(Address(rsp, -32), xmm0);
938 __ vmovdqu(xmm0, Address(rsp, src_offset));
939 __ vmovdqu(Address(rsp, dst_offset), xmm0);
940 __ vmovdqu(xmm0, Address(rsp, -32));
941 break;
942 default:
943 ShouldNotReachHere();
944 }
945 int size = __ offset() - offset;
946 assert(size == calc_size, "incorrect size calculattion");
947 return size;
948 #ifndef PRODUCT
949 } else if (!do_size) {
950 switch (ireg) {
951 case Op_VecS:
952 st->print("pushl [rsp + #%d]\t# 32-bit mem-mem spill\n\t"
953 "popl [rsp + #%d]",
954 src_offset, dst_offset);
955 break;
956 case Op_VecD:
957 st->print("pushl [rsp + #%d]\t# 64-bit mem-mem spill\n\t"
958 "popq [rsp + #%d]\n\t"
959 "pushl [rsp + #%d]\n\t"
960 "popq [rsp + #%d]",
961 src_offset, dst_offset, src_offset+4, dst_offset+4);
962 break;
963 case Op_VecX:
964 st->print("movdqu [rsp - #16], xmm0\t# 128-bit mem-mem spill\n\t"
965 "movdqu xmm0, [rsp + #%d]\n\t"
966 "movdqu [rsp + #%d], xmm0\n\t"
967 "movdqu xmm0, [rsp - #16]",
968 src_offset, dst_offset);
969 break;
970 case Op_VecY:
971 st->print("vmovdqu [rsp - #32], xmm0\t# 256-bit mem-mem spill\n\t"
972 "vmovdqu xmm0, [rsp + #%d]\n\t"
973 "vmovdqu [rsp + #%d], xmm0\n\t"
974 "vmovdqu xmm0, [rsp - #32]",
975 src_offset, dst_offset);
976 break;
977 default:
978 ShouldNotReachHere();
979 }
980 #endif
981 }
982 return calc_size;
983 }
984
985 uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, PhaseRegAlloc *ra_, bool do_size, outputStream* st ) const {
986 // Get registers to move
987 OptoReg::Name src_second = ra_->get_reg_second(in(1));
988 OptoReg::Name src_first = ra_->get_reg_first(in(1));
989 OptoReg::Name dst_second = ra_->get_reg_second(this );
990 OptoReg::Name dst_first = ra_->get_reg_first(this );
991
992 enum RC src_second_rc = rc_class(src_second);
993 enum RC src_first_rc = rc_class(src_first);
994 enum RC dst_second_rc = rc_class(dst_second);
995 enum RC dst_first_rc = rc_class(dst_first);
996
997 assert( OptoReg::is_valid(src_first) && OptoReg::is_valid(dst_first), "must move at least 1 register" );
998
999 // Generate spill code!
1000 int size = 0;
1001
1002 if( src_first == dst_first && src_second == dst_second )
1003 return size; // Self copy, no move
1004
1005 if (bottom_type()->isa_vect() != NULL) {
1006 uint ireg = ideal_reg();
1007 assert((src_first_rc != rc_int && dst_first_rc != rc_int), "sanity");
1008 assert((src_first_rc != rc_float && dst_first_rc != rc_float), "sanity");
1009 assert((ireg == Op_VecS || ireg == Op_VecD || ireg == Op_VecX || ireg == Op_VecY), "sanity");
1010 if( src_first_rc == rc_stack && dst_first_rc == rc_stack ) {
1011 // mem -> mem
1012 int src_offset = ra_->reg2offset(src_first);
1013 int dst_offset = ra_->reg2offset(dst_first);
1014 return vec_stack_to_stack_helper(cbuf, do_size, src_offset, dst_offset, ireg, st);
1015 } else if (src_first_rc == rc_xmm && dst_first_rc == rc_xmm ) {
1016 return vec_mov_helper(cbuf, do_size, src_first, dst_first, src_second, dst_second, ireg, st);
1017 } else if (src_first_rc == rc_xmm && dst_first_rc == rc_stack ) {
1018 int stack_offset = ra_->reg2offset(dst_first);
1019 return vec_spill_helper(cbuf, do_size, false, stack_offset, src_first, ireg, st);
1020 } else if (src_first_rc == rc_stack && dst_first_rc == rc_xmm ) {
1021 int stack_offset = ra_->reg2offset(src_first);
1022 return vec_spill_helper(cbuf, do_size, true, stack_offset, dst_first, ireg, st);
1023 } else {
1024 ShouldNotReachHere();
1025 }
1026 }
1027
1028 // --------------------------------------
1029 // Check for mem-mem move. push/pop to move.
3952 predicate( UseSSE < 2 );
3953 constraint(ALLOC_IN_RC(fp_flt_reg));
3954 match(RegF);
3955 match(regFPR1);
3956 format %{ %}
3957 interface(REG_INTER);
3958 %}
3959
3960 // Float register operands
3961 operand regFPR1(regFPR reg) %{
3962 predicate( UseSSE < 2 );
3963 constraint(ALLOC_IN_RC(fp_flt_reg0));
3964 match(reg);
3965 format %{ "FPR1" %}
3966 interface(REG_INTER);
3967 %}
3968
3969 // XMM Float register operands
3970 operand regF() %{
3971 predicate( UseSSE>=1 );
3972 constraint(ALLOC_IN_RC(float_reg));
3973 match(RegF);
3974 format %{ %}
3975 interface(REG_INTER);
3976 %}
3977
3978 // XMM Double register operands
3979 operand regD() %{
3980 predicate( UseSSE>=2 );
3981 constraint(ALLOC_IN_RC(double_reg));
3982 match(RegD);
3983 format %{ %}
3984 interface(REG_INTER);
3985 %}
3986
3987
3988 //----------Memory Operands----------------------------------------------------
3989 // Direct Memory Operand
3990 operand direct(immP addr) %{
3991 match(addr);
3992
3993 format %{ "[$addr]" %}
3994 interface(MEMORY_INTER) %{
3995 base(0xFFFFFFFF);
3996 index(0x4);
3997 scale(0x0);
3998 disp($addr);
3999 %}
4000 %}
4001
4002 // Indirect Memory Operand
4003 operand indirect(eRegP reg) %{
4004 constraint(ALLOC_IN_RC(int_reg));
4005 match(reg);
4006
11122 match(Set dst (ConvL2F src));
11123 effect( KILL cr );
11124 format %{ "PUSH $src.hi\t# Convert long to single float\n\t"
11125 "PUSH $src.lo\n\t"
11126 "FILD ST,[ESP + #0]\n\t"
11127 "ADD ESP,8\n\t"
11128 "FSTP_S $dst\t# F-round" %}
11129 opcode(0xDF, 0x5); /* DF /5 */
11130 ins_encode(convert_long_double(src), Pop_Mem_FPR(dst));
11131 ins_pipe( pipe_slow );
11132 %}
11133
11134 instruct convL2I_reg( rRegI dst, eRegL src ) %{
11135 match(Set dst (ConvL2I src));
11136 effect( DEF dst, USE src );
11137 format %{ "MOV $dst,$src.lo" %}
11138 ins_encode(enc_CopyL_Lo(dst,src));
11139 ins_pipe( ialu_reg_reg );
11140 %}
11141
11142
11143 instruct MoveF2I_stack_reg(rRegI dst, stackSlotF src) %{
11144 match(Set dst (MoveF2I src));
11145 effect( DEF dst, USE src );
11146 ins_cost(100);
11147 format %{ "MOV $dst,$src\t# MoveF2I_stack_reg" %}
11148 ins_encode %{
11149 __ movl($dst$$Register, Address(rsp, $src$$disp));
11150 %}
11151 ins_pipe( ialu_reg_mem );
11152 %}
11153
11154 instruct MoveFPR2I_reg_stack(stackSlotI dst, regFPR src) %{
11155 predicate(UseSSE==0);
11156 match(Set dst (MoveF2I src));
11157 effect( DEF dst, USE src );
11158
11159 ins_cost(125);
11160 format %{ "FST_S $dst,$src\t# MoveF2I_reg_stack" %}
11161 ins_encode( Pop_Mem_Reg_FPR(dst, src) );
11162 ins_pipe( fpu_mem_reg );
|
84 // the stack will not have this element so FPR1 == st(0) from the
85 // oopMap viewpoint. This same weirdness with numbering causes
86 // instruction encoding to have to play games with the register
87 // encode to correct for this 0/1 issue. See MachSpillCopyNode::implementation
88 // where it does flt->flt moves to see an example
89 //
90 reg_def FPR1L( SOC, SOC, Op_RegF, 1, as_FloatRegister(0)->as_VMReg());
91 reg_def FPR1H( SOC, SOC, Op_RegF, 1, as_FloatRegister(0)->as_VMReg()->next());
92 reg_def FPR2L( SOC, SOC, Op_RegF, 2, as_FloatRegister(1)->as_VMReg());
93 reg_def FPR2H( SOC, SOC, Op_RegF, 2, as_FloatRegister(1)->as_VMReg()->next());
94 reg_def FPR3L( SOC, SOC, Op_RegF, 3, as_FloatRegister(2)->as_VMReg());
95 reg_def FPR3H( SOC, SOC, Op_RegF, 3, as_FloatRegister(2)->as_VMReg()->next());
96 reg_def FPR4L( SOC, SOC, Op_RegF, 4, as_FloatRegister(3)->as_VMReg());
97 reg_def FPR4H( SOC, SOC, Op_RegF, 4, as_FloatRegister(3)->as_VMReg()->next());
98 reg_def FPR5L( SOC, SOC, Op_RegF, 5, as_FloatRegister(4)->as_VMReg());
99 reg_def FPR5H( SOC, SOC, Op_RegF, 5, as_FloatRegister(4)->as_VMReg()->next());
100 reg_def FPR6L( SOC, SOC, Op_RegF, 6, as_FloatRegister(5)->as_VMReg());
101 reg_def FPR6H( SOC, SOC, Op_RegF, 6, as_FloatRegister(5)->as_VMReg()->next());
102 reg_def FPR7L( SOC, SOC, Op_RegF, 7, as_FloatRegister(6)->as_VMReg());
103 reg_def FPR7H( SOC, SOC, Op_RegF, 7, as_FloatRegister(6)->as_VMReg()->next());
104 //
105 // Empty fill registers, which are never used, but supply alignment to xmm regs
106 //
107 reg_def FILL0( SOC, SOC, Op_RegF, 7, as_FloatRegister(6)->as_VMReg()->next(2));
108 reg_def FILL1( SOC, SOC, Op_RegF, 7, as_FloatRegister(6)->as_VMReg()->next(3));
109 reg_def FILL2( SOC, SOC, Op_RegF, 7, as_FloatRegister(6)->as_VMReg()->next(4));
110 reg_def FILL3( SOC, SOC, Op_RegF, 7, as_FloatRegister(6)->as_VMReg()->next(5));
111 reg_def FILL4( SOC, SOC, Op_RegF, 7, as_FloatRegister(6)->as_VMReg()->next(6));
112 reg_def FILL5( SOC, SOC, Op_RegF, 7, as_FloatRegister(6)->as_VMReg()->next(7));
113 reg_def FILL6( SOC, SOC, Op_RegF, 7, as_FloatRegister(6)->as_VMReg()->next(8));
114 reg_def FILL7( SOC, SOC, Op_RegF, 7, as_FloatRegister(6)->as_VMReg()->next(9));
115
116 // Specify priority of register selection within phases of register
117 // allocation. Highest priority is first. A useful heuristic is to
118 // give registers a low priority when they are required by machine
119 // instructions, like EAX and EDX. Registers which are used as
120 // pairs must fall on an even boundary (witness the FPR#L's in this list).
121 // For the Intel integer registers, the equivalent Long pairs are
122 // EDX:EAX, EBX:ECX, and EDI:EBP.
123 alloc_class chunk0( ECX, EBX, EBP, EDI, EAX, EDX, ESI, ESP,
124 FPR0L, FPR0H, FPR1L, FPR1H, FPR2L, FPR2H,
125 FPR3L, FPR3H, FPR4L, FPR4H, FPR5L, FPR5H,
126 FPR6L, FPR6H, FPR7L, FPR7H,
127 FILL0, FILL1, FILL2, FILL3, FILL4, FILL5, FILL6, FILL7);
128
129
130 //----------Architecture Description Register Classes--------------------------
131 // Several register classes are automatically defined based upon information in
132 // this architecture description.
133 // 1) reg_class inline_cache_reg ( /* as def'd in frame section */ )
134 // 2) reg_class compiler_method_oop_reg ( /* as def'd in frame section */ )
135 // 2) reg_class interpreter_method_oop_reg ( /* as def'd in frame section */ )
136 // 3) reg_class stack_slots( /* one chunk of stack-based "registers" */ )
137 //
138 // Class for all registers
139 reg_class any_reg(EAX, EDX, EBP, EDI, ESI, ECX, EBX, ESP);
140 // Class for general registers
141 reg_class int_reg(EAX, EDX, EBP, EDI, ESI, ECX, EBX);
142 // Class for general registers which may be used for implicit null checks on win95
143 // Also safe for use by tailjump. We don't want to allocate in rbp,
144 reg_class int_reg_no_rbp(EAX, EDX, EDI, ESI, ECX, EBX);
145 // Class of "X" registers
146 reg_class int_x_reg(EBX, ECX, EDX, EAX);
147 // Class of registers that can appear in an address with no offset.
230 return operand;
231 }
232
233 // Buffer for 128-bits masks used by SSE instructions.
234 static jlong fp_signmask_pool[(4+1)*2]; // 4*128bits(data) + 128bits(alignment)
235
236 // Static initialization during VM startup.
237 static jlong *float_signmask_pool = double_quadword(&fp_signmask_pool[1*2], CONST64(0x7FFFFFFF7FFFFFFF), CONST64(0x7FFFFFFF7FFFFFFF));
238 static jlong *double_signmask_pool = double_quadword(&fp_signmask_pool[2*2], CONST64(0x7FFFFFFFFFFFFFFF), CONST64(0x7FFFFFFFFFFFFFFF));
239 static jlong *float_signflip_pool = double_quadword(&fp_signmask_pool[3*2], CONST64(0x8000000080000000), CONST64(0x8000000080000000));
240 static jlong *double_signflip_pool = double_quadword(&fp_signmask_pool[4*2], CONST64(0x8000000000000000), CONST64(0x8000000000000000));
241
242 // Offset hacking within calls.
243 static int pre_call_resets_size() {
244 int size = 0;
245 Compile* C = Compile::current();
246 if (C->in_24_bit_fp_mode()) {
247 size += 6; // fldcw
248 }
249 if (C->max_vector_size() > 16) {
250 if(UseAVX <= 2) {
251 size += 3; // vzeroupper
252 }
253 }
254 return size;
255 }
256
257 static int preserve_SP_size() {
258 return 2; // op, rm(reg/reg)
259 }
260
261 // !!!!! Special hack to get all type of calls to specify the byte offset
262 // from the start of the call to the point where the return address
263 // will point.
264 int MachCallStaticJavaNode::ret_addr_offset() {
265 int offset = 5 + pre_call_resets_size(); // 5 bytes from start of call to where return address points
266 if (_method_handle_invoke)
267 offset += preserve_SP_size();
268 return offset;
269 }
270
271 int MachCallDynamicJavaNode::ret_addr_offset() {
272 return 10 + pre_call_resets_size(); // 10 bytes from start of call to where return address points
273 }
728 emit_opcode (*cbuf, opcode );
729 encode_RegMem(*cbuf, Matcher::_regEncode[reg], ESP_enc, 0x4, 0, offset, relocInfo::none);
730 #ifndef PRODUCT
731 } else if( !do_size ) {
732 if( size != 0 ) st->print("\n\t");
733 if( opcode == 0x8B || opcode == 0x89 ) { // MOV
734 if( is_load ) st->print("%s %s,[ESP + #%d]",op_str,Matcher::regName[reg],offset);
735 else st->print("%s [ESP + #%d],%s",op_str,offset,Matcher::regName[reg]);
736 } else { // FLD, FST, PUSH, POP
737 st->print("%s [ESP + #%d]",op_str,offset);
738 }
739 #endif
740 }
741 int offset_size = (offset == 0) ? 0 : ((offset <= 127) ? 1 : 4);
742 return size+3+offset_size;
743 }
744
745 // Helper for XMM registers. Extra opcode bits, limited syntax.
746 static int impl_x_helper( CodeBuffer *cbuf, bool do_size, bool is_load,
747 int offset, int reg_lo, int reg_hi, int size, outputStream* st ) {
748 int in_size_in_bits = Assembler::EVEX_32bit;
749 int evex_encoding = 0;
750 if (reg_lo+1 == reg_hi) {
751 in_size_in_bits = Assembler::EVEX_64bit;
752 evex_encoding = Assembler::VEX_W;
753 }
754 if (cbuf) {
755 MacroAssembler _masm(cbuf);
756 if (reg_lo+1 == reg_hi) { // double move?
757 if (is_load) {
758 __ movdbl(as_XMMRegister(Matcher::_regEncode[reg_lo]), Address(rsp, offset));
759 } else {
760 __ movdbl(Address(rsp, offset), as_XMMRegister(Matcher::_regEncode[reg_lo]));
761 }
762 } else {
763 if (is_load) {
764 __ movflt(as_XMMRegister(Matcher::_regEncode[reg_lo]), Address(rsp, offset));
765 } else {
766 __ movflt(Address(rsp, offset), as_XMMRegister(Matcher::_regEncode[reg_lo]));
767 }
768 }
769 #ifndef PRODUCT
770 } else if (!do_size) {
771 if (size != 0) st->print("\n\t");
772 if (reg_lo+1 == reg_hi) { // double move?
773 if (is_load) st->print("%s %s,[ESP + #%d]",
774 UseXmmLoadAndClearUpper ? "MOVSD " : "MOVLPD",
775 Matcher::regName[reg_lo], offset);
776 else st->print("MOVSD [ESP + #%d],%s",
777 offset, Matcher::regName[reg_lo]);
778 } else {
779 if (is_load) st->print("MOVSS %s,[ESP + #%d]",
780 Matcher::regName[reg_lo], offset);
781 else st->print("MOVSS [ESP + #%d],%s",
782 offset, Matcher::regName[reg_lo]);
783 }
784 #endif
785 }
786 bool is_single_byte = false;
787 if ((UseAVX > 2) && (offset != 0)) {
788 is_single_byte = Assembler::query_compressed_disp_byte(offset, true, 0, Assembler::EVEX_T1S, in_size_in_bits, evex_encoding);
789 }
790 int offset_size = 0;
791 if (UseAVX > 2 ) {
792 offset_size = (offset == 0) ? 0 : ((is_single_byte) ? 1 : 4);
793 } else {
794 offset_size = (offset == 0) ? 0 : ((offset <= 127) ? 1 : 4);
795 }
796 size += (UseAVX > 2) ? 2 : 0; // Need an additional two bytes for EVEX
797 // VEX_2bytes prefix is used if UseAVX > 0, so it takes the same 2 bytes as SIMD prefix.
798 return size+5+offset_size;
799 }
800
801
802 static int impl_movx_helper( CodeBuffer *cbuf, bool do_size, int src_lo, int dst_lo,
803 int src_hi, int dst_hi, int size, outputStream* st ) {
804 if (cbuf) {
805 MacroAssembler _masm(cbuf);
806 if (src_lo+1 == src_hi && dst_lo+1 == dst_hi) { // double move?
807 __ movdbl(as_XMMRegister(Matcher::_regEncode[dst_lo]),
808 as_XMMRegister(Matcher::_regEncode[src_lo]));
809 } else {
810 __ movflt(as_XMMRegister(Matcher::_regEncode[dst_lo]),
811 as_XMMRegister(Matcher::_regEncode[src_lo]));
812 }
813 #ifndef PRODUCT
814 } else if (!do_size) {
815 if (size != 0) st->print("\n\t");
816 if (UseXmmRegToRegMoveAll) {//Use movaps,movapd to move between xmm registers
817 if (src_lo+1 == src_hi && dst_lo+1 == dst_hi) { // double move?
818 st->print("MOVAPD %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]);
819 } else {
820 st->print("MOVAPS %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]);
821 }
822 } else {
823 if( src_lo+1 == src_hi && dst_lo+1 == dst_hi ) { // double move?
824 st->print("MOVSD %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]);
825 } else {
826 st->print("MOVSS %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]);
827 }
828 }
829 #endif
830 }
831 // VEX_2bytes prefix is used if UseAVX > 0, and it takes the same 2 bytes as SIMD prefix.
832 // Only MOVAPS SSE prefix uses 1 byte. EVEX uses an additional 2 bytes.
833 int sz = (UseAVX > 2) ? 6 : 4;
834 if (!(src_lo+1 == src_hi && dst_lo+1 == dst_hi) &&
835 UseXmmRegToRegMoveAll && (UseAVX == 0)) sz = 3;
836 return size + sz;
837 }
838
839 static int impl_movgpr2x_helper( CodeBuffer *cbuf, bool do_size, int src_lo, int dst_lo,
840 int src_hi, int dst_hi, int size, outputStream* st ) {
841 // 32-bit
842 if (cbuf) {
843 MacroAssembler _masm(cbuf);
844 __ movdl(as_XMMRegister(Matcher::_regEncode[dst_lo]),
845 as_Register(Matcher::_regEncode[src_lo]));
846 #ifndef PRODUCT
847 } else if (!do_size) {
848 st->print("movdl %s, %s\t# spill", Matcher::regName[dst_lo], Matcher::regName[src_lo]);
849 #endif
850 }
851 return (UseAVX> 2) ? 6 : 4;
852 }
853
854
855 static int impl_movx2gpr_helper( CodeBuffer *cbuf, bool do_size, int src_lo, int dst_lo,
856 int src_hi, int dst_hi, int size, outputStream* st ) {
857 // 32-bit
858 if (cbuf) {
859 MacroAssembler _masm(cbuf);
860 __ movdl(as_Register(Matcher::_regEncode[dst_lo]),
861 as_XMMRegister(Matcher::_regEncode[src_lo]));
862 #ifndef PRODUCT
863 } else if (!do_size) {
864 st->print("movdl %s, %s\t# spill", Matcher::regName[dst_lo], Matcher::regName[src_lo]);
865 #endif
866 }
867 return (UseAVX> 2) ? 6 : 4;
868 }
869
870 static int impl_mov_helper( CodeBuffer *cbuf, bool do_size, int src, int dst, int size, outputStream* st ) {
871 if( cbuf ) {
872 emit_opcode(*cbuf, 0x8B );
873 emit_rm (*cbuf, 0x3, Matcher::_regEncode[dst], Matcher::_regEncode[src] );
874 #ifndef PRODUCT
875 } else if( !do_size ) {
876 if( size != 0 ) st->print("\n\t");
877 st->print("MOV %s,%s",Matcher::regName[dst],Matcher::regName[src]);
878 #endif
879 }
880 return size+2;
881 }
882
883 static int impl_fp_store_helper( CodeBuffer *cbuf, bool do_size, int src_lo, int src_hi, int dst_lo, int dst_hi,
884 int offset, int size, outputStream* st ) {
885 if( src_lo != FPR1L_num ) { // Move value to top of FP stack, if not already there
886 if( cbuf ) {
887 emit_opcode( *cbuf, 0xD9 ); // FLD (i.e., push it)
918 int stack_offset, int reg, uint ireg, outputStream* st);
919
920 static int vec_stack_to_stack_helper(CodeBuffer *cbuf, bool do_size, int src_offset,
921 int dst_offset, uint ireg, outputStream* st) {
922 int calc_size = 0;
923 int src_offset_size = (src_offset == 0) ? 0 : ((src_offset < 0x80) ? 1 : 4);
924 int dst_offset_size = (dst_offset == 0) ? 0 : ((dst_offset < 0x80) ? 1 : 4);
925 switch (ireg) {
926 case Op_VecS:
927 calc_size = 3+src_offset_size + 3+dst_offset_size;
928 break;
929 case Op_VecD:
930 calc_size = 3+src_offset_size + 3+dst_offset_size;
931 src_offset += 4;
932 dst_offset += 4;
933 src_offset_size = (src_offset == 0) ? 0 : ((src_offset < 0x80) ? 1 : 4);
934 dst_offset_size = (dst_offset == 0) ? 0 : ((dst_offset < 0x80) ? 1 : 4);
935 calc_size += 3+src_offset_size + 3+dst_offset_size;
936 break;
937 case Op_VecX:
938 case Op_VecY:
939 case Op_VecZ:
940 calc_size = 6 + 6 + 5+src_offset_size + 5+dst_offset_size;
941 break;
942 default:
943 ShouldNotReachHere();
944 }
945 if (cbuf) {
946 MacroAssembler _masm(cbuf);
947 int offset = __ offset();
948 switch (ireg) {
949 case Op_VecS:
950 __ pushl(Address(rsp, src_offset));
951 __ popl (Address(rsp, dst_offset));
952 break;
953 case Op_VecD:
954 __ pushl(Address(rsp, src_offset));
955 __ popl (Address(rsp, dst_offset));
956 __ pushl(Address(rsp, src_offset+4));
957 __ popl (Address(rsp, dst_offset+4));
958 break;
959 case Op_VecX:
960 __ movdqu(Address(rsp, -16), xmm0);
961 __ movdqu(xmm0, Address(rsp, src_offset));
962 __ movdqu(Address(rsp, dst_offset), xmm0);
963 __ movdqu(xmm0, Address(rsp, -16));
964 break;
965 case Op_VecY:
966 __ vmovdqu(Address(rsp, -32), xmm0);
967 __ vmovdqu(xmm0, Address(rsp, src_offset));
968 __ vmovdqu(Address(rsp, dst_offset), xmm0);
969 __ vmovdqu(xmm0, Address(rsp, -32));
970 case Op_VecZ:
971 __ evmovdqu(Address(rsp, -64), xmm0, 2);
972 __ evmovdqu(xmm0, Address(rsp, src_offset), 2);
973 __ evmovdqu(Address(rsp, dst_offset), xmm0, 2);
974 __ evmovdqu(xmm0, Address(rsp, -64), 2);
975 break;
976 default:
977 ShouldNotReachHere();
978 }
979 int size = __ offset() - offset;
980 assert(size == calc_size, "incorrect size calculattion");
981 return size;
982 #ifndef PRODUCT
983 } else if (!do_size) {
984 switch (ireg) {
985 case Op_VecS:
986 st->print("pushl [rsp + #%d]\t# 32-bit mem-mem spill\n\t"
987 "popl [rsp + #%d]",
988 src_offset, dst_offset);
989 break;
990 case Op_VecD:
991 st->print("pushl [rsp + #%d]\t# 64-bit mem-mem spill\n\t"
992 "popq [rsp + #%d]\n\t"
993 "pushl [rsp + #%d]\n\t"
994 "popq [rsp + #%d]",
995 src_offset, dst_offset, src_offset+4, dst_offset+4);
996 break;
997 case Op_VecX:
998 st->print("movdqu [rsp - #16], xmm0\t# 128-bit mem-mem spill\n\t"
999 "movdqu xmm0, [rsp + #%d]\n\t"
1000 "movdqu [rsp + #%d], xmm0\n\t"
1001 "movdqu xmm0, [rsp - #16]",
1002 src_offset, dst_offset);
1003 break;
1004 case Op_VecY:
1005 st->print("vmovdqu [rsp - #32], xmm0\t# 256-bit mem-mem spill\n\t"
1006 "vmovdqu xmm0, [rsp + #%d]\n\t"
1007 "vmovdqu [rsp + #%d], xmm0\n\t"
1008 "vmovdqu xmm0, [rsp - #32]",
1009 src_offset, dst_offset);
1010 case Op_VecZ:
1011 st->print("vmovdqu [rsp - #64], xmm0\t# 512-bit mem-mem spill\n\t"
1012 "vmovdqu xmm0, [rsp + #%d]\n\t"
1013 "vmovdqu [rsp + #%d], xmm0\n\t"
1014 "vmovdqu xmm0, [rsp - #64]",
1015 src_offset, dst_offset);
1016 break;
1017 default:
1018 ShouldNotReachHere();
1019 }
1020 #endif
1021 }
1022 return calc_size;
1023 }
1024
1025 uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, PhaseRegAlloc *ra_, bool do_size, outputStream* st ) const {
1026 // Get registers to move
1027 OptoReg::Name src_second = ra_->get_reg_second(in(1));
1028 OptoReg::Name src_first = ra_->get_reg_first(in(1));
1029 OptoReg::Name dst_second = ra_->get_reg_second(this );
1030 OptoReg::Name dst_first = ra_->get_reg_first(this );
1031
1032 enum RC src_second_rc = rc_class(src_second);
1033 enum RC src_first_rc = rc_class(src_first);
1034 enum RC dst_second_rc = rc_class(dst_second);
1035 enum RC dst_first_rc = rc_class(dst_first);
1036
1037 assert( OptoReg::is_valid(src_first) && OptoReg::is_valid(dst_first), "must move at least 1 register" );
1038
1039 // Generate spill code!
1040 int size = 0;
1041
1042 if( src_first == dst_first && src_second == dst_second )
1043 return size; // Self copy, no move
1044
1045 if (bottom_type()->isa_vect() != NULL) {
1046 uint ireg = ideal_reg();
1047 assert((src_first_rc != rc_int && dst_first_rc != rc_int), "sanity");
1048 assert((src_first_rc != rc_float && dst_first_rc != rc_float), "sanity");
1049 assert((ireg == Op_VecS || ireg == Op_VecD || ireg == Op_VecX || ireg == Op_VecY || ireg == Op_VecZ ), "sanity");
1050 if( src_first_rc == rc_stack && dst_first_rc == rc_stack ) {
1051 // mem -> mem
1052 int src_offset = ra_->reg2offset(src_first);
1053 int dst_offset = ra_->reg2offset(dst_first);
1054 return vec_stack_to_stack_helper(cbuf, do_size, src_offset, dst_offset, ireg, st);
1055 } else if (src_first_rc == rc_xmm && dst_first_rc == rc_xmm ) {
1056 return vec_mov_helper(cbuf, do_size, src_first, dst_first, src_second, dst_second, ireg, st);
1057 } else if (src_first_rc == rc_xmm && dst_first_rc == rc_stack ) {
1058 int stack_offset = ra_->reg2offset(dst_first);
1059 return vec_spill_helper(cbuf, do_size, false, stack_offset, src_first, ireg, st);
1060 } else if (src_first_rc == rc_stack && dst_first_rc == rc_xmm ) {
1061 int stack_offset = ra_->reg2offset(src_first);
1062 return vec_spill_helper(cbuf, do_size, true, stack_offset, dst_first, ireg, st);
1063 } else {
1064 ShouldNotReachHere();
1065 }
1066 }
1067
1068 // --------------------------------------
1069 // Check for mem-mem move. push/pop to move.
3992 predicate( UseSSE < 2 );
3993 constraint(ALLOC_IN_RC(fp_flt_reg));
3994 match(RegF);
3995 match(regFPR1);
3996 format %{ %}
3997 interface(REG_INTER);
3998 %}
3999
4000 // Float register operands
4001 operand regFPR1(regFPR reg) %{
4002 predicate( UseSSE < 2 );
4003 constraint(ALLOC_IN_RC(fp_flt_reg0));
4004 match(reg);
4005 format %{ "FPR1" %}
4006 interface(REG_INTER);
4007 %}
4008
4009 // XMM Float register operands
4010 operand regF() %{
4011 predicate( UseSSE>=1 );
4012 constraint(ALLOC_IN_RC(float_reg_legacy));
4013 match(RegF);
4014 format %{ %}
4015 interface(REG_INTER);
4016 %}
4017
4018 // XMM Double register operands
4019 operand regD() %{
4020 predicate( UseSSE>=2 );
4021 constraint(ALLOC_IN_RC(double_reg_legacy));
4022 match(RegD);
4023 format %{ %}
4024 interface(REG_INTER);
4025 %}
4026
4027 // Vectors
4028 operand vecS() %{
4029 constraint(ALLOC_IN_RC(vectors_reg_legacy));
4030 match(VecS);
4031
4032 format %{ %}
4033 interface(REG_INTER);
4034 %}
4035
4036 operand vecD() %{
4037 constraint(ALLOC_IN_RC(vectord_reg_legacy));
4038 match(VecD);
4039
4040 format %{ %}
4041 interface(REG_INTER);
4042 %}
4043
4044 operand vecX() %{
4045 constraint(ALLOC_IN_RC(vectorx_reg_legacy));
4046 match(VecX);
4047
4048 format %{ %}
4049 interface(REG_INTER);
4050 %}
4051
4052 operand vecY() %{
4053 constraint(ALLOC_IN_RC(vectory_reg_legacy));
4054 match(VecY);
4055
4056 format %{ %}
4057 interface(REG_INTER);
4058 %}
4059
4060 //----------Memory Operands----------------------------------------------------
4061 // Direct Memory Operand
4062 operand direct(immP addr) %{
4063 match(addr);
4064
4065 format %{ "[$addr]" %}
4066 interface(MEMORY_INTER) %{
4067 base(0xFFFFFFFF);
4068 index(0x4);
4069 scale(0x0);
4070 disp($addr);
4071 %}
4072 %}
4073
4074 // Indirect Memory Operand
4075 operand indirect(eRegP reg) %{
4076 constraint(ALLOC_IN_RC(int_reg));
4077 match(reg);
4078
11194 match(Set dst (ConvL2F src));
11195 effect( KILL cr );
11196 format %{ "PUSH $src.hi\t# Convert long to single float\n\t"
11197 "PUSH $src.lo\n\t"
11198 "FILD ST,[ESP + #0]\n\t"
11199 "ADD ESP,8\n\t"
11200 "FSTP_S $dst\t# F-round" %}
11201 opcode(0xDF, 0x5); /* DF /5 */
11202 ins_encode(convert_long_double(src), Pop_Mem_FPR(dst));
11203 ins_pipe( pipe_slow );
11204 %}
11205
11206 instruct convL2I_reg( rRegI dst, eRegL src ) %{
11207 match(Set dst (ConvL2I src));
11208 effect( DEF dst, USE src );
11209 format %{ "MOV $dst,$src.lo" %}
11210 ins_encode(enc_CopyL_Lo(dst,src));
11211 ins_pipe( ialu_reg_reg );
11212 %}
11213
11214 instruct MoveF2I_stack_reg(rRegI dst, stackSlotF src) %{
11215 match(Set dst (MoveF2I src));
11216 effect( DEF dst, USE src );
11217 ins_cost(100);
11218 format %{ "MOV $dst,$src\t# MoveF2I_stack_reg" %}
11219 ins_encode %{
11220 __ movl($dst$$Register, Address(rsp, $src$$disp));
11221 %}
11222 ins_pipe( ialu_reg_mem );
11223 %}
11224
11225 instruct MoveFPR2I_reg_stack(stackSlotI dst, regFPR src) %{
11226 predicate(UseSSE==0);
11227 match(Set dst (MoveF2I src));
11228 effect( DEF dst, USE src );
11229
11230 ins_cost(125);
11231 format %{ "FST_S $dst,$src\t# MoveF2I_reg_stack" %}
11232 ins_encode( Pop_Mem_Reg_FPR(dst, src) );
11233 ins_pipe( fpu_mem_reg );
|