--- old/src/cpu/sparc/vm/assembler_sparc.hpp Wed Jul 6 14:42:52 2011 +++ new/src/cpu/sparc/vm/assembler_sparc.hpp Wed Jul 6 14:42:52 2011 @@ -716,6 +716,8 @@ casa_op3 = 0x3c, casxa_op3 = 0x3e, + mftoi_op3 = 0x36, + alt_bit_op3 = 0x10, cc_bit_op3 = 0x10 }; @@ -750,7 +752,13 @@ fitod_opf = 0xc8, fstod_opf = 0xc9, fstoi_opf = 0xd1, - fdtoi_opf = 0xd2 + fdtoi_opf = 0xd2, + + mdtox_opf = 0x110, + mstouw_opf = 0x111, + mstosw_opf = 0x113, + mxtod_opf = 0x118, + mwtos_opf = 0x119 }; enum RCondition { rc_z = 1, rc_lez = 2, rc_lz = 3, rc_nz = 5, rc_gz = 6, rc_gez = 7 }; @@ -1061,6 +1069,9 @@ return x & ((1 << 10) - 1); } + // instruction only in VIS3 + static void vis3_only() { assert( VM_Version::has_vis3(), "This instruction only works on SPARC with VIS3"); } + // instruction only in v9 static void v9_only() { assert( VM_Version::v9_instructions_work(), "This instruction only works on SPARC V9"); } @@ -1247,8 +1258,8 @@ // pp 159 - void ftox( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { v9_only(); emit_long( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0x80 + w) | fs2(s, w)); } - void ftoi( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { emit_long( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0xd0 + w) | fs2(s, w)); } + void ftox( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { v9_only(); emit_long( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(fpop1_op3) | opf(0x80 + w) | fs2(s, w)); } + void ftoi( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { emit_long( op(arith_op) | fd(d, FloatRegisterImpl::S) | op3(fpop1_op3) | opf(0xd0 + w) | fs2(s, w)); } // pp 160 @@ -1256,8 +1267,8 @@ // pp 161 - void fxtof( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { v9_only(); emit_long( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0x80 + w*4) | fs2(s, w)); } - void fitof( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { emit_long( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0xc0 + w*4) | fs2(s, w)); } + void fxtof( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { v9_only(); emit_long( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0x80 + w*4) | fs2(s, FloatRegisterImpl::D)); } + void fitof( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { emit_long( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0xc0 + w*4) | fs2(s, FloatRegisterImpl::S)); } // pp 162 @@ -1709,6 +1720,19 @@ inline void wrasi( Register d) { v9_only(); emit_long( op(arith_op) | rs1(d) | op3(wrreg_op3) | u_field(3, 29, 25)); } inline void wrfprs( Register d) { v9_only(); emit_long( op(arith_op) | rs1(d) | op3(wrreg_op3) | u_field(6, 29, 25)); } + + // VIS3 instructions + + void movstosw( FloatRegister s, Register d ) { vis3_only(); emit_long( op(arith_op) | rd(d) | op3(mftoi_op3) | opf(mstosw_opf) | fs2(s, FloatRegisterImpl::S)); } + void movstouw( FloatRegister s, Register d ) { vis3_only(); emit_long( op(arith_op) | rd(d) | op3(mftoi_op3) | opf(mstouw_opf) | fs2(s, FloatRegisterImpl::S)); } + void movdtox( FloatRegister s, Register d ) { vis3_only(); emit_long( op(arith_op) | rd(d) | op3(mftoi_op3) | opf(mdtox_opf) | fs2(s, FloatRegisterImpl::D)); } + + void movwtos( Register s, FloatRegister d ) { vis3_only(); emit_long( op(arith_op) | fd(d, FloatRegisterImpl::S) | op3(mftoi_op3) | opf(mwtos_opf) | rs2(s)); } + void movxtod( Register s, FloatRegister d ) { vis3_only(); emit_long( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(mftoi_op3) | opf(mxtod_opf) | rs2(s)); } + + + + // For a given register condition, return the appropriate condition code // Condition (the one you would use to get the same effect after "tst" on // the target register.) --- old/src/cpu/sparc/vm/sparc.ad Wed Jul 6 14:42:53 2011 +++ new/src/cpu/sparc/vm/sparc.ad Wed Jul 6 14:42:53 2011 @@ -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,9 +1326,9 @@ // -------------------------------------- // 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); @@ -1335,8 +1335,8 @@ 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,7 +8401,18 @@ %} %} +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)); format %{ "FSTOD $src,$dst" %} @@ -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,7 +8482,18 @@ %} %} +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); format %{ "FITOD $tmp,$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); + stkI_to_regF(tmp, src); + convI2D_helper(dst, tmp); %} %} -instruct convI2D_mem( regD_low dst, memory mem ) %{ +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,103 +8604,7 @@ 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. // Still useful because cheetah traps and becomes @@ -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) %{ --- old/src/cpu/sparc/vm/vm_version_sparc.cpp Wed Jul 6 14:42:54 2011 +++ new/src/cpu/sparc/vm/vm_version_sparc.cpp Wed Jul 6 14:42:54 2011 @@ -144,6 +144,18 @@ // buf is started with ", " or is empty _features_str = strdup(strlen(buf) > 2 ? buf + 2 : buf); + // UseVIS is set to the smallest of what hardware supports and what + // the command line requires. I.e., you cannot set UseVIS to 3 on + // older UltraSparc which do not support it. + if( UseVIS > 3 ) UseVIS=3; + if( UseVIS < 0 ) UseVIS=0; + if( !has_vis3() ) // Drop to 2 if no VIS3 support + UseVIS = MIN2((intx)2,UseVIS); + if( !has_vis2() ) // Drop to 1 if no VIS2 support + UseVIS = MIN2((intx)1,UseVIS); + if( !has_vis1() ) // Drop to 0 if no VIS1 support + UseVIS = 0; + #ifndef PRODUCT if (PrintMiscellaneous && Verbose) { tty->print("Allocation: "); --- old/src/share/vm/runtime/globals.hpp Wed Jul 6 14:42:55 2011 +++ new/src/share/vm/runtime/globals.hpp Wed Jul 6 14:42:54 2011 @@ -492,6 +492,9 @@ product(intx, UseSSE, 99, \ "Highest supported SSE instructions set on x86/x64") \ \ + product(intx, UseVIS, 99, \ + "Highest supported VIS instructions set on Sparc") \ + \ product(uintx, LargePageSizeInBytes, 0, \ "Large page size (0 to let VM choose the page size") \ \