src/cpu/sparc/vm/sparc.ad
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File
*** 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

*** 423,433 **** --- 423,433 ---- // Paired floating point registers--they show up in the same order as the floats, // 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 ); %} //----------DEFINITION BLOCK--------------------------------------------------- // Define name --> value mappings to inform the ADLC of an integer valued name // Current support includes integer values in the range [0, 0x7FFFFFFF]
*** 1324,1353 **** --- 1324,1368 ---- src_second_rc = rc_float; } // -------------------------------------- // 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); st->print("\tADD R_SP,16,R_SP\n"); } #endif 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 // hardware does the flop for me. Doubles are always aligned, so no problem // there. Misaligned sources only come from native-long-returns (handled
*** 8162,8171 **** --- 8177,8335 ---- "MOVlt $tmp,$p\t! p' < 0 ? p'+y : p'" %} ins_encode( enc_cadd_cmpLTMask(p, q, y, tmp) ); 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! instruct convD2F_reg(regF dst, regD src) %{ match(Set dst (ConvD2F src));
*** 8189,8208 **** --- 8353,8384 ---- "skip:" %} ins_encode(form_d2i_helper(src,dst)); 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 %{ regF tmp; convD2I_helper(tmp, src); regF_to_stkI(dst, tmp); %} %} + 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) %{ effect(DEF dst, USE src, KILL fcc0); format %{ "FCMPd fcc0,$src,$src\t! check for NAN\n\t"
*** 8213,8244 **** --- 8389,8431 ---- "skip:" %} ins_encode(form_d2l_helper(src,dst)); 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 %{ regD tmp; convD2L_helper(tmp, src); regD_to_stkL(dst, tmp); %} %} + 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" %} opcode(Assembler::fpop1_op3, Assembler::arith_op, Assembler::fstod_opf); ins_encode(form3_opf_rs2F_rdD(src, dst)); ins_pipe(fcvtF2D); %} + // 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" "FBO,pt fcc0,skip\t! branch on ordered, predict taken\n\t" "FSTOI $src,$dst\t! convert in delay slot\n\t"
*** 8247,8267 **** --- 8434,8467 ---- "skip:" %} ins_encode(form_f2i_helper(src,dst)); 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 %{ regF tmp; convF2I_helper(tmp, src); regF_to_stkI(dst, tmp); %} %} + 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" "FBO,pt fcc0,skip\t! branch on ordered, predict taken\n\t" "FSTOX $src,$dst\t! convert in delay slot\n\t"
*** 8270,8310 **** --- 8470,8530 ---- "skip:" %} ins_encode(form_f2l_helper(src,dst)); 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 %{ regD tmp; convF2L_helper(tmp, src); regD_to_stkL(dst, tmp); %} %} + 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" %} opcode(Assembler::fpop1_op3, Assembler::arith_op, Assembler::fitod_opf); ins_encode(form3_opf_rs2F_rdD(tmp, dst)); 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 ) %{ ! 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); format %{ "LDF $mem,$dst\n\t" "FITOD $dst,$dst" %}
*** 8320,8339 **** --- 8540,8570 ---- opcode(Assembler::fpop1_op3, Assembler::arith_op, Assembler::fitos_opf); ins_encode(form3_opf_rs2F_rdF(tmp, dst)); 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 %{ regF tmp; stkI_to_regF(tmp,src); convI2F_helper(dst, tmp); %} %} + 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); size(8); format %{ "LDF $mem,$dst\n\t"
*** 8371,8477 **** --- 8602,8612 ---- opcode(Assembler::srl_op3, Assembler::arith_op); ins_encode( form3_rs1_rs2_rd( src, R_G0, dst ) ); 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 // amazingly slow for some common numbers.
*** 8587,8597 **** --- 8722,8732 ---- opcode(Assembler::fpop1_op3, Assembler::arith_op, Assembler::fxtod_opf); ins_encode(form3_opf_rs2D_rdD(tmp, dst)); 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); expand %{ regD tmp;
*** 8598,8611 **** --- 8733,8751 ---- stkL_to_regD(tmp, src); convL2D_helper(dst, tmp); %} %} //----------- // 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) %{ effect(DEF dst, USE tmp); size(4);
*** 8613,8631 **** --- 8753,8783 ---- opcode(Assembler::fpop1_op3, Assembler::arith_op, Assembler::fxtos_opf); ins_encode(form3_opf_rs2D_rdF(tmp, dst)); 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 %{ regD tmp; stkL_to_regD(tmp, 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) %{ match(Set dst (ConvL2I src)); #ifndef _LP64

src/cpu/sparc/vm/sparc.ad
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File