提交 b2659942 编写于 作者: K kvn

7059034: Use movxtod/movdtox on T4

Summary: Use new VIS3 mov instructions on T4 for move data between general and float registers.
Reviewed-by: never, twisti
上级 153b0b58
......@@ -716,6 +716,8 @@ class Assembler : public AbstractAssembler {
casa_op3 = 0x3c,
casxa_op3 = 0x3e,
mftoi_op3 = 0x36,
alt_bit_op3 = 0x10,
cc_bit_op3 = 0x10
};
......@@ -750,7 +752,13 @@ class Assembler : public AbstractAssembler {
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 @@ class Assembler : public AbstractAssembler {
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 @@ public:
// 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 @@ public:
// 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 @@ public:
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.)
......
......@@ -425,7 +425,7 @@ reg_class dflt_reg(R_F0, R_F1, R_F2, R_F3, R_F4, R_F5, R_F6, R_F7, R_F8, R_F9, R
// 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 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf,
// --------------------------------------
// 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 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf,
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 @@ instruct cadd_cmpLTMask( iRegI p, iRegI q, iRegI y, iRegI tmp, flagsReg ccr ) %{
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 @@ instruct convD2I_helper(regF dst, regD src, flagsRegF0 fcc0) %{
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(stackSlotI dst, regD src) %{
%}
%}
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 @@ instruct convD2L_helper(regD dst, regD src, flagsRegF0 fcc0) %{
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(stackSlotL dst, regD src) %{
%}
%}
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 @@ instruct convF2D_reg(regD dst, regF src) %{
%}
// 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 @@ instruct convF2I_helper(regF dst, regF src, flagsRegF0 fcc0) %{
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(stackSlotI dst, regF src) %{
%}
%}
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 @@ instruct convF2L_helper(regD dst, regF src, flagsRegF0 fcc0) %{
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(stackSlotL dst, regF src) %{
%}
%}
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 @@ instruct convI2D_helper(regD dst, regF tmp) %{
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 @@ instruct convI2F_helper(regF dst, regF tmp) %{
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, stackSlotI src ) %{
%}
%}
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 @@ instruct zerox_long(iRegL dst, iRegL src, immL_32bits mask ) %{
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 @@ instruct convL2D_helper(regD dst, regD tmp) %{
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 @@ instruct convL2D_reg_fast_fxtof(regD dst, stackSlotL src) %{
%}
%}
//-----------
// 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 @@ instruct convL2F_helper(regF dst, regD tmp) %{
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 @@ instruct convL2F_reg_fast_fxtof(regF dst, stackSlotL src) %{
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) %{
......
......@@ -144,6 +144,18 @@ void VM_Version::initialize() {
// 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: ");
......
......@@ -492,6 +492,9 @@ class CommandLineFlags {
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") \
\
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册