diff -r b16582d6c7db -r faa472957b38 src/cpu/sparc/vm/sparc.ad --- a/src/cpu/sparc/vm/sparc.ad Thu Jul 07 10:51:07 2011 -0700 +++ b/src/cpu/sparc/vm/sparc.ad Fri Jul 08 09:38:48 2011 -0700 @@ -425,7 +425,7 @@ // but they are used with the "Op_RegD" type, and always occur in even/odd pairs. // This class is usable for mis-aligned loads as happen in I2C adapters. reg_class dflt_low_reg(R_F0, R_F1, R_F2, R_F3, R_F4, R_F5, R_F6, R_F7, R_F8, R_F9, R_F10,R_F11,R_F12,R_F13,R_F14,R_F15, - R_F16,R_F17,R_F18,R_F19,R_F20,R_F21,R_F22,R_F23,R_F24,R_F25,R_F26,R_F27,R_F28,R_F29,R_F30,R_F31 ); + R_F16,R_F17,R_F18,R_F19,R_F20,R_F21,R_F22,R_F23,R_F24,R_F25,R_F26,R_F27,R_F28,R_F29); %} //----------DEFINITION BLOCK--------------------------------------------------- @@ -1326,17 +1326,17 @@ // -------------------------------------- // Check for float->int copy; requires a trip through memory - if( src_first_rc == rc_float && dst_first_rc == rc_int ) { + if (src_first_rc == rc_float && dst_first_rc == rc_int && UseVIS < 3) { int offset = frame::register_save_words*wordSize; - if( cbuf ) { + if (cbuf) { emit3_simm13( *cbuf, Assembler::arith_op, R_SP_enc, Assembler::sub_op3, R_SP_enc, 16 ); impl_helper(this,cbuf,ra_,do_size,false,offset,src_first,Assembler::stf_op3 ,"STF ",size, st); impl_helper(this,cbuf,ra_,do_size,true ,offset,dst_first,Assembler::lduw_op3,"LDUW",size, st); emit3_simm13( *cbuf, Assembler::arith_op, R_SP_enc, Assembler::add_op3, R_SP_enc, 16 ); } #ifndef PRODUCT - else if( !do_size ) { - if( size != 0 ) st->print("\n\t"); + else if (!do_size) { + if (size != 0) st->print("\n\t"); st->print( "SUB R_SP,16,R_SP\n"); impl_helper(this,cbuf,ra_,do_size,false,offset,src_first,Assembler::stf_op3 ,"STF ",size, st); impl_helper(this,cbuf,ra_,do_size,true ,offset,dst_first,Assembler::lduw_op3,"LDUW",size, st); @@ -1346,6 +1346,21 @@ size += 16; } + // Check for float->int copy on T4 + if (src_first_rc == rc_float && dst_first_rc == rc_int && UseVIS >= 3) { + // Further check for aligned-adjacent pair, so we can use a double move + if ((src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second) + return impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::mftoi_op3,Assembler::mdtox_opf,"MOVDTOX",size, st); + size = impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::mftoi_op3,Assembler::mstouw_opf,"MOVSTOUW",size, st); + } + // Check for int->float copy on T4 + if (src_first_rc == rc_int && dst_first_rc == rc_float && UseVIS >= 3) { + // Further check for aligned-adjacent pair, so we can use a double move + if ((src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second) + return impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::mftoi_op3,Assembler::mxtod_opf,"MOVXTOD",size, st); + size = impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::mftoi_op3,Assembler::mwtos_opf,"MOVWTOS",size, st); + } + // -------------------------------------- // In the 32-bit 1-reg-longs build ONLY, I see mis-aligned long destinations. // In such cases, I have to do the big-endian swap. For aligned targets, the @@ -8164,6 +8179,155 @@ ins_pipe( cadd_cmpltmask ); %} + +//----------------------------------------------------------------- +// Direct raw moves between float and general registers using VIS3. + +// ins_pipe(faddF_reg); +instruct MoveF2I_reg_reg(iRegI dst, regF src) %{ + predicate(UseVIS >= 3); + match(Set dst (MoveF2I src)); + + format %{ "MOVSTOUW $src,$dst\t! MoveF2I" %} + ins_encode %{ + __ movstouw($src$$FloatRegister, $dst$$Register); + %} + ins_pipe(ialu_reg_reg); +%} + +instruct MoveI2F_reg_reg(regF dst, iRegI src) %{ + predicate(UseVIS >= 3); + match(Set dst (MoveI2F src)); + + format %{ "MOVWTOS $src,$dst\t! MoveI2F" %} + ins_encode %{ + __ movwtos($src$$Register, $dst$$FloatRegister); + %} + ins_pipe(ialu_reg_reg); +%} + +instruct MoveD2L_reg_reg(iRegL dst, regD src) %{ + predicate(UseVIS >= 3); + match(Set dst (MoveD2L src)); + + format %{ "MOVDTOX $src,$dst\t! MoveD2L" %} + ins_encode %{ + __ movdtox(as_DoubleFloatRegister($src$$reg), $dst$$Register); + %} + ins_pipe(ialu_reg_reg); +%} + +instruct MoveL2D_reg_reg(regD dst, iRegL src) %{ + predicate(UseVIS >= 3); + match(Set dst (MoveL2D src)); + + format %{ "MOVXTOD $src,$dst\t! MoveL2D" %} + ins_encode %{ + __ movxtod($src$$Register, as_DoubleFloatRegister($dst$$reg)); + %} + ins_pipe(ialu_reg_reg); +%} + + +// Raw moves between float and general registers using stack. + +instruct MoveF2I_stack_reg(iRegI dst, stackSlotF src) %{ + match(Set dst (MoveF2I src)); + effect(DEF dst, USE src); + ins_cost(MEMORY_REF_COST); + + size(4); + format %{ "LDUW $src,$dst\t! MoveF2I" %} + opcode(Assembler::lduw_op3); + ins_encode(simple_form3_mem_reg( src, dst ) ); + ins_pipe(iload_mem); +%} + +instruct MoveI2F_stack_reg(regF dst, stackSlotI src) %{ + match(Set dst (MoveI2F src)); + effect(DEF dst, USE src); + ins_cost(MEMORY_REF_COST); + + size(4); + format %{ "LDF $src,$dst\t! MoveI2F" %} + opcode(Assembler::ldf_op3); + ins_encode(simple_form3_mem_reg(src, dst)); + ins_pipe(floadF_stk); +%} + +instruct MoveD2L_stack_reg(iRegL dst, stackSlotD src) %{ + match(Set dst (MoveD2L src)); + effect(DEF dst, USE src); + ins_cost(MEMORY_REF_COST); + + size(4); + format %{ "LDX $src,$dst\t! MoveD2L" %} + opcode(Assembler::ldx_op3); + ins_encode(simple_form3_mem_reg( src, dst ) ); + ins_pipe(iload_mem); +%} + +instruct MoveL2D_stack_reg(regD dst, stackSlotL src) %{ + match(Set dst (MoveL2D src)); + effect(DEF dst, USE src); + ins_cost(MEMORY_REF_COST); + + size(4); + format %{ "LDDF $src,$dst\t! MoveL2D" %} + opcode(Assembler::lddf_op3); + ins_encode(simple_form3_mem_reg(src, dst)); + ins_pipe(floadD_stk); +%} + +instruct MoveF2I_reg_stack(stackSlotI dst, regF src) %{ + match(Set dst (MoveF2I src)); + effect(DEF dst, USE src); + ins_cost(MEMORY_REF_COST); + + size(4); + format %{ "STF $src,$dst\t! MoveF2I" %} + opcode(Assembler::stf_op3); + ins_encode(simple_form3_mem_reg(dst, src)); + ins_pipe(fstoreF_stk_reg); +%} + +instruct MoveI2F_reg_stack(stackSlotF dst, iRegI src) %{ + match(Set dst (MoveI2F src)); + effect(DEF dst, USE src); + ins_cost(MEMORY_REF_COST); + + size(4); + format %{ "STW $src,$dst\t! MoveI2F" %} + opcode(Assembler::stw_op3); + ins_encode(simple_form3_mem_reg( dst, src ) ); + ins_pipe(istore_mem_reg); +%} + +instruct MoveD2L_reg_stack(stackSlotL dst, regD src) %{ + match(Set dst (MoveD2L src)); + effect(DEF dst, USE src); + ins_cost(MEMORY_REF_COST); + + size(4); + format %{ "STDF $src,$dst\t! MoveD2L" %} + opcode(Assembler::stdf_op3); + ins_encode(simple_form3_mem_reg(dst, src)); + ins_pipe(fstoreD_stk_reg); +%} + +instruct MoveL2D_reg_stack(stackSlotD dst, iRegL src) %{ + match(Set dst (MoveL2D src)); + effect(DEF dst, USE src); + ins_cost(MEMORY_REF_COST); + + size(4); + format %{ "STX $src,$dst\t! MoveL2D" %} + opcode(Assembler::stx_op3); + ins_encode(simple_form3_mem_reg( dst, src ) ); + ins_pipe(istore_mem_reg); +%} + + //----------Arithmetic Conversion Instructions--------------------------------- // The conversions operations are all Alpha sorted. Please keep it that way! @@ -8191,7 +8355,7 @@ ins_pipe(fcvtD2I); %} -instruct convD2I_reg(stackSlotI dst, regD src) %{ +instruct convD2I_stk(stackSlotI dst, regD src) %{ match(Set dst (ConvD2I src)); ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); expand %{ @@ -8201,6 +8365,18 @@ %} %} +instruct convD2I_reg(iRegI dst, regD src) %{ + predicate(UseVIS >= 3); + match(Set dst (ConvD2I src)); + ins_cost(DEFAULT_COST*2 + BRANCH_COST); + expand %{ + regF tmp; + convD2I_helper(tmp, src); + MoveF2I_reg_reg(dst, tmp); + %} +%} + + // Convert a double to a long in a double register. // If the double is a NAN, stuff a zero in instead. instruct convD2L_helper(regD dst, regD src, flagsRegF0 fcc0) %{ @@ -8215,9 +8391,7 @@ ins_pipe(fcvtD2L); %} - -// Double to Long conversion -instruct convD2L_reg(stackSlotL dst, regD src) %{ +instruct convD2L_stk(stackSlotL dst, regD src) %{ match(Set dst (ConvD2L src)); ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); expand %{ @@ -8227,6 +8401,17 @@ %} %} +instruct convD2L_reg(iRegL dst, regD src) %{ + predicate(UseVIS >= 3); + match(Set dst (ConvD2L src)); + ins_cost(DEFAULT_COST*2 + BRANCH_COST); + expand %{ + regD tmp; + convD2L_helper(tmp, src); + MoveD2L_reg_reg(dst, tmp); + %} +%} + instruct convF2D_reg(regD dst, regF src) %{ match(Set dst (ConvF2D src)); @@ -8237,6 +8422,8 @@ %} +// Convert a float to an int in a float register. +// If the float is a NAN, stuff a zero in instead. instruct convF2I_helper(regF dst, regF src, flagsRegF0 fcc0) %{ effect(DEF dst, USE src, KILL fcc0); format %{ "FCMPs fcc0,$src,$src\t! check for NAN\n\t" @@ -8249,7 +8436,7 @@ ins_pipe(fcvtF2I); %} -instruct convF2I_reg(stackSlotI dst, regF src) %{ +instruct convF2I_stk(stackSlotI dst, regF src) %{ match(Set dst (ConvF2I src)); ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); expand %{ @@ -8259,7 +8446,20 @@ %} %} - +instruct convF2I_reg(iRegI dst, regF src) %{ + predicate(UseVIS >= 3); + match(Set dst (ConvF2I src)); + ins_cost(DEFAULT_COST*2 + BRANCH_COST); + expand %{ + regF tmp; + convF2I_helper(tmp, src); + MoveF2I_reg_reg(dst, tmp); + %} +%} + + +// Convert a float to a long in a float register. +// If the float is a NAN, stuff a zero in instead. instruct convF2L_helper(regD dst, regF src, flagsRegF0 fcc0) %{ effect(DEF dst, USE src, KILL fcc0); format %{ "FCMPs fcc0,$src,$src\t! check for NAN\n\t" @@ -8272,8 +8472,7 @@ ins_pipe(fcvtF2L); %} -// Float to Long conversion -instruct convF2L_reg(stackSlotL dst, regF src) %{ +instruct convF2L_stk(stackSlotL dst, regF src) %{ match(Set dst (ConvF2L src)); ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); expand %{ @@ -8283,6 +8482,17 @@ %} %} +instruct convF2L_reg(iRegL dst, regF src) %{ + predicate(UseVIS >= 3); + match(Set dst (ConvF2L src)); + ins_cost(DEFAULT_COST*2 + BRANCH_COST); + expand %{ + regD tmp; + convF2L_helper(tmp, src); + MoveD2L_reg_reg(dst, tmp); + %} +%} + instruct convI2D_helper(regD dst, regF tmp) %{ effect(USE tmp, DEF dst); @@ -8292,17 +8502,27 @@ ins_pipe(fcvtI2D); %} -instruct convI2D_reg(stackSlotI src, regD dst) %{ +instruct convI2D_stk(stackSlotI src, regD dst) %{ match(Set dst (ConvI2D src)); ins_cost(DEFAULT_COST + MEMORY_REF_COST); expand %{ regF tmp; - stkI_to_regF( tmp, src); - convI2D_helper( dst, tmp); - %} -%} - -instruct convI2D_mem( regD_low dst, memory mem ) %{ + stkI_to_regF(tmp, src); + convI2D_helper(dst, tmp); + %} +%} + +instruct convI2D_reg(regD_low dst, iRegI src) %{ + predicate(UseVIS >= 3); + match(Set dst (ConvI2D src)); + expand %{ + regF tmp; + MoveI2F_reg_reg(tmp, src); + convI2D_helper(dst, tmp); + %} +%} + +instruct convI2D_mem(regD_low dst, memory mem) %{ match(Set dst (ConvI2D (LoadI mem))); ins_cost(DEFAULT_COST + MEMORY_REF_COST); size(8); @@ -8322,7 +8542,7 @@ ins_pipe(fcvtI2F); %} -instruct convI2F_reg( regF dst, stackSlotI src ) %{ +instruct convI2F_stk(regF dst, stackSlotI src) %{ match(Set dst (ConvI2F src)); ins_cost(DEFAULT_COST + MEMORY_REF_COST); expand %{ @@ -8332,6 +8552,17 @@ %} %} +instruct convI2F_reg(regF dst, iRegI src) %{ + predicate(UseVIS >= 3); + match(Set dst (ConvI2F src)); + ins_cost(DEFAULT_COST); + expand %{ + regF tmp; + MoveI2F_reg_reg(tmp, src); + convI2F_helper(dst, tmp); + %} +%} + instruct convI2F_mem( regF dst, memory mem ) %{ match(Set dst (ConvI2F (LoadI mem))); ins_cost(DEFAULT_COST + MEMORY_REF_COST); @@ -8373,102 +8604,6 @@ ins_pipe(ialu_reg_reg); %} -instruct MoveF2I_stack_reg(iRegI dst, stackSlotF src) %{ - match(Set dst (MoveF2I src)); - effect(DEF dst, USE src); - ins_cost(MEMORY_REF_COST); - - size(4); - format %{ "LDUW $src,$dst\t! MoveF2I" %} - opcode(Assembler::lduw_op3); - ins_encode(simple_form3_mem_reg( src, dst ) ); - ins_pipe(iload_mem); -%} - -instruct MoveI2F_stack_reg(regF dst, stackSlotI src) %{ - match(Set dst (MoveI2F src)); - effect(DEF dst, USE src); - ins_cost(MEMORY_REF_COST); - - size(4); - format %{ "LDF $src,$dst\t! MoveI2F" %} - opcode(Assembler::ldf_op3); - ins_encode(simple_form3_mem_reg(src, dst)); - ins_pipe(floadF_stk); -%} - -instruct MoveD2L_stack_reg(iRegL dst, stackSlotD src) %{ - match(Set dst (MoveD2L src)); - effect(DEF dst, USE src); - ins_cost(MEMORY_REF_COST); - - size(4); - format %{ "LDX $src,$dst\t! MoveD2L" %} - opcode(Assembler::ldx_op3); - ins_encode(simple_form3_mem_reg( src, dst ) ); - ins_pipe(iload_mem); -%} - -instruct MoveL2D_stack_reg(regD dst, stackSlotL src) %{ - match(Set dst (MoveL2D src)); - effect(DEF dst, USE src); - ins_cost(MEMORY_REF_COST); - - size(4); - format %{ "LDDF $src,$dst\t! MoveL2D" %} - opcode(Assembler::lddf_op3); - ins_encode(simple_form3_mem_reg(src, dst)); - ins_pipe(floadD_stk); -%} - -instruct MoveF2I_reg_stack(stackSlotI dst, regF src) %{ - match(Set dst (MoveF2I src)); - effect(DEF dst, USE src); - ins_cost(MEMORY_REF_COST); - - size(4); - format %{ "STF $src,$dst\t!MoveF2I" %} - opcode(Assembler::stf_op3); - ins_encode(simple_form3_mem_reg(dst, src)); - ins_pipe(fstoreF_stk_reg); -%} - -instruct MoveI2F_reg_stack(stackSlotF dst, iRegI src) %{ - match(Set dst (MoveI2F src)); - effect(DEF dst, USE src); - ins_cost(MEMORY_REF_COST); - - size(4); - format %{ "STW $src,$dst\t!MoveI2F" %} - opcode(Assembler::stw_op3); - ins_encode(simple_form3_mem_reg( dst, src ) ); - ins_pipe(istore_mem_reg); -%} - -instruct MoveD2L_reg_stack(stackSlotL dst, regD src) %{ - match(Set dst (MoveD2L src)); - effect(DEF dst, USE src); - ins_cost(MEMORY_REF_COST); - - size(4); - format %{ "STDF $src,$dst\t!MoveD2L" %} - opcode(Assembler::stdf_op3); - ins_encode(simple_form3_mem_reg(dst, src)); - ins_pipe(fstoreD_stk_reg); -%} - -instruct MoveL2D_reg_stack(stackSlotD dst, iRegL src) %{ - match(Set dst (MoveL2D src)); - effect(DEF dst, USE src); - ins_cost(MEMORY_REF_COST); - - size(4); - format %{ "STX $src,$dst\t!MoveL2D" %} - opcode(Assembler::stx_op3); - ins_encode(simple_form3_mem_reg( dst, src ) ); - ins_pipe(istore_mem_reg); -%} - //----------- // Long to Double conversion using V8 opcodes. @@ -8589,7 +8724,7 @@ ins_pipe(fcvtL2D); %} -instruct convL2D_reg_fast_fxtof(regD dst, stackSlotL src) %{ +instruct convL2D_stk_fast_fxtof(regD dst, stackSlotL src) %{ predicate(VM_Version::has_fast_fxtof()); match(Set dst (ConvL2D src)); ins_cost(DEFAULT_COST + 3 * MEMORY_REF_COST); @@ -8600,10 +8735,15 @@ %} %} -//----------- -// Long to Float conversion using V8 opcodes. -// Still useful because cheetah traps and becomes -// amazingly slow for some common numbers. +instruct convL2D_reg(regD dst, iRegL src) %{ + predicate(UseVIS >= 3); + match(Set dst (ConvL2D src)); + expand %{ + regD tmp; + MoveL2D_reg_reg(tmp, src); + convL2D_helper(dst, tmp); + %} +%} // Long to Float conversion using fast fxtof instruct convL2F_helper(regF dst, regD tmp) %{ @@ -8615,7 +8755,7 @@ ins_pipe(fcvtL2F); %} -instruct convL2F_reg_fast_fxtof(regF dst, stackSlotL src) %{ +instruct convL2F_stk_fast_fxtof(regF dst, stackSlotL src) %{ match(Set dst (ConvL2F src)); ins_cost(DEFAULT_COST + MEMORY_REF_COST); expand %{ @@ -8624,6 +8764,18 @@ convL2F_helper(dst, tmp); %} %} + +instruct convL2F_reg(regF dst, iRegL src) %{ + predicate(UseVIS >= 3); + match(Set dst (ConvL2F src)); + ins_cost(DEFAULT_COST); + expand %{ + regD tmp; + MoveL2D_reg_reg(tmp, src); + convL2F_helper(dst, tmp); + %} +%} + //----------- instruct convL2I_reg(iRegI dst, iRegL src) %{