Mercurial > hg > graal-jvmci-8
comparison src/cpu/sparc/vm/sparc.ad @ 2008:2f644f85485d
6961690: load oops from constant table on SPARC
Summary: oops should be loaded from the constant table of an nmethod instead of materializing them with a long code sequence.
Reviewed-by: never, kvn
author | twisti |
---|---|
date | Fri, 03 Dec 2010 01:34:31 -0800 |
parents | 885e464e1a40 |
children | 5fe0781a8560 |
comparison
equal
deleted
inserted
replaced
2007:5ddfcf4b079e | 2008:2f644f85485d |
---|---|
665 offset = atype->is_ptr()->_offset; | 665 offset = atype->is_ptr()->_offset; |
666 if (offset != Type::OffsetBot) offset += disp32; | 666 if (offset != Type::OffsetBot) offset += disp32; |
667 return offset; | 667 return offset; |
668 } | 668 } |
669 | 669 |
670 static inline jdouble replicate_immI(int con, int count, int width) { | |
671 // Load a constant replicated "count" times with width "width" | |
672 int bit_width = width * 8; | |
673 jlong elt_val = con; | |
674 elt_val &= (((jlong) 1) << bit_width) - 1; // mask off sign bits | |
675 jlong val = elt_val; | |
676 for (int i = 0; i < count - 1; i++) { | |
677 val <<= bit_width; | |
678 val |= elt_val; | |
679 } | |
680 jdouble dval = *((jdouble*) &val); // coerce to double type | |
681 return dval; | |
682 } | |
683 | |
670 // Standard Sparc opcode form2 field breakdown | 684 // Standard Sparc opcode form2 field breakdown |
671 static inline void emit2_19(CodeBuffer &cbuf, int f30, int f29, int f25, int f22, int f20, int f19, int f0 ) { | 685 static inline void emit2_19(CodeBuffer &cbuf, int f30, int f29, int f25, int f22, int f20, int f19, int f0 ) { |
672 f0 &= (1<<19)-1; // Mask displacement to 19 bits | 686 f0 &= (1<<19)-1; // Mask displacement to 19 bits |
673 int op = (f30 << 30) | | 687 int op = (f30 << 30) | |
674 (f29 << 29) | | 688 (f29 << 29) | |
1006 void emit_lo(CodeBuffer &cbuf, int val) { } | 1020 void emit_lo(CodeBuffer &cbuf, int val) { } |
1007 void emit_hi(CodeBuffer &cbuf, int val) { } | 1021 void emit_hi(CodeBuffer &cbuf, int val) { } |
1008 | 1022 |
1009 | 1023 |
1010 //============================================================================= | 1024 //============================================================================= |
1025 const bool Matcher::constant_table_absolute_addressing = false; | |
1026 const RegMask& MachConstantBaseNode::_out_RegMask = PTR_REG_mask; | |
1027 | |
1028 void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const { | |
1029 Compile* C = ra_->C; | |
1030 Compile::ConstantTable& constant_table = C->constant_table(); | |
1031 MacroAssembler _masm(&cbuf); | |
1032 | |
1033 Register r = as_Register(ra_->get_encode(this)); | |
1034 CodeSection* cs = __ code()->consts(); | |
1035 int consts_size = cs->align_at_start(cs->size()); | |
1036 | |
1037 if (UseRDPCForConstantTableBase) { | |
1038 // For the following RDPC logic to work correctly the consts | |
1039 // section must be allocated right before the insts section. This | |
1040 // assert checks for that. The layout and the SECT_* constants | |
1041 // are defined in src/share/vm/asm/codeBuffer.hpp. | |
1042 assert(CodeBuffer::SECT_CONSTS + 1 == CodeBuffer::SECT_INSTS, "must be"); | |
1043 int offset = __ offset(); | |
1044 int disp; | |
1045 | |
1046 // If the displacement from the current PC to the constant table | |
1047 // base fits into simm13 we set the constant table base to the | |
1048 // current PC. | |
1049 if (__ is_simm13(-(consts_size + offset))) { | |
1050 constant_table.set_table_base_offset(-(consts_size + offset)); | |
1051 disp = 0; | |
1052 } else { | |
1053 // If the offset of the top constant (last entry in the table) | |
1054 // fits into simm13 we set the constant table base to the actual | |
1055 // table base. | |
1056 if (__ is_simm13(constant_table.top_offset())) { | |
1057 constant_table.set_table_base_offset(0); | |
1058 disp = consts_size + offset; | |
1059 } else { | |
1060 // Otherwise we set the constant table base in the middle of the | |
1061 // constant table. | |
1062 int half_consts_size = consts_size / 2; | |
1063 assert(half_consts_size * 2 == consts_size, "sanity"); | |
1064 constant_table.set_table_base_offset(-half_consts_size); // table base offset gets added to the load displacement. | |
1065 disp = half_consts_size + offset; | |
1066 } | |
1067 } | |
1068 | |
1069 __ rdpc(r); | |
1070 | |
1071 if (disp != 0) { | |
1072 assert(r != O7, "need temporary"); | |
1073 __ sub(r, __ ensure_simm13_or_reg(disp, O7), r); | |
1074 } | |
1075 } | |
1076 else { | |
1077 // Materialize the constant table base. | |
1078 assert(constant_table.size() == consts_size, err_msg("must be: %d == %d", constant_table.size(), consts_size)); | |
1079 address baseaddr = cs->start() + -(constant_table.table_base_offset()); | |
1080 RelocationHolder rspec = internal_word_Relocation::spec(baseaddr); | |
1081 AddressLiteral base(baseaddr, rspec); | |
1082 __ set(base, r); | |
1083 } | |
1084 } | |
1085 | |
1086 uint MachConstantBaseNode::size(PhaseRegAlloc*) const { | |
1087 if (UseRDPCForConstantTableBase) { | |
1088 // This is really the worst case but generally it's only 1 instruction. | |
1089 return 4 /*rdpc*/ + 4 /*sub*/ + MacroAssembler::worst_case_size_of_set(); | |
1090 } else { | |
1091 return MacroAssembler::worst_case_size_of_set(); | |
1092 } | |
1093 } | |
1094 | |
1095 #ifndef PRODUCT | |
1096 void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const { | |
1097 char reg[128]; | |
1098 ra_->dump_register(this, reg); | |
1099 if (UseRDPCForConstantTableBase) { | |
1100 st->print("RDPC %s\t! constant table base", reg); | |
1101 } else { | |
1102 st->print("SET &constanttable,%s\t! constant table base", reg); | |
1103 } | |
1104 } | |
1105 #endif | |
1106 | |
1107 | |
1108 //============================================================================= | |
1011 | 1109 |
1012 #ifndef PRODUCT | 1110 #ifndef PRODUCT |
1013 void MachPrologNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { | 1111 void MachPrologNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { |
1014 Compile* C = ra_->C; | 1112 Compile* C = ra_->C; |
1015 | 1113 |
2245 | 2343 |
2246 __ fbp( (Assembler::Condition)($cmp$$cmpcode), false, (Assembler::CC)($cc$$reg), predict_taken, L); | 2344 __ fbp( (Assembler::Condition)($cmp$$cmpcode), false, (Assembler::CC)($cc$$reg), predict_taken, L); |
2247 __ delayed()->nop(); | 2345 __ delayed()->nop(); |
2248 %} | 2346 %} |
2249 | 2347 |
2250 enc_class jump_enc( iRegX switch_val, o7RegI table) %{ | |
2251 MacroAssembler _masm(&cbuf); | |
2252 | |
2253 Register switch_reg = as_Register($switch_val$$reg); | |
2254 Register table_reg = O7; | |
2255 | |
2256 address table_base = __ address_table_constant(_index2label); | |
2257 RelocationHolder rspec = internal_word_Relocation::spec(table_base); | |
2258 | |
2259 // Move table address into a register. | |
2260 __ set(table_base, table_reg, rspec); | |
2261 | |
2262 // Jump to base address + switch value | |
2263 __ ld_ptr(table_reg, switch_reg, table_reg); | |
2264 __ jmp(table_reg, G0); | |
2265 __ delayed()->nop(); | |
2266 | |
2267 %} | |
2268 | |
2269 enc_class enc_ba( Label labl ) %{ | 2348 enc_class enc_ba( Label labl ) %{ |
2270 MacroAssembler _masm(&cbuf); | 2349 MacroAssembler _masm(&cbuf); |
2271 Label &L = *($labl$$label); | 2350 Label &L = *($labl$$label); |
2272 __ ba(false, L); | 2351 __ ba(false, L); |
2273 __ delayed()->nop(); | 2352 __ delayed()->nop(); |
2382 (0 << 11) | // cc1, cc0 bits for 'icc' | 2461 (0 << 11) | // cc1, cc0 bits for 'icc' |
2383 ($src$$reg << 0); | 2462 ($src$$reg << 0); |
2384 cbuf.insts()->emit_int32(op); | 2463 cbuf.insts()->emit_int32(op); |
2385 %} | 2464 %} |
2386 | 2465 |
2387 // Utility encoding for loading a 64 bit Pointer into a register | |
2388 // The 64 bit pointer is stored in the generated code stream | |
2389 enc_class SetPtr( immP src, iRegP rd ) %{ | |
2390 Register dest = reg_to_register_object($rd$$reg); | |
2391 MacroAssembler _masm(&cbuf); | |
2392 // [RGV] This next line should be generated from ADLC | |
2393 if ( _opnds[1]->constant_is_oop() ) { | |
2394 intptr_t val = $src$$constant; | |
2395 __ set_oop_constant((jobject)val, dest); | |
2396 } else { // non-oop pointers, e.g. card mark base, heap top | |
2397 __ set($src$$constant, dest); | |
2398 } | |
2399 %} | |
2400 | |
2401 enc_class Set13( immI13 src, iRegI rd ) %{ | 2466 enc_class Set13( immI13 src, iRegI rd ) %{ |
2402 emit3_simm13( cbuf, Assembler::arith_op, $rd$$reg, Assembler::or_op3, 0, $src$$constant ); | 2467 emit3_simm13( cbuf, Assembler::arith_op, $rd$$reg, Assembler::or_op3, 0, $src$$constant ); |
2403 %} | 2468 %} |
2404 | 2469 |
2405 enc_class SetHi22( immI src, iRegI rd ) %{ | 2470 enc_class SetHi22( immI src, iRegI rd ) %{ |
2407 %} | 2472 %} |
2408 | 2473 |
2409 enc_class Set32( immI src, iRegI rd ) %{ | 2474 enc_class Set32( immI src, iRegI rd ) %{ |
2410 MacroAssembler _masm(&cbuf); | 2475 MacroAssembler _masm(&cbuf); |
2411 __ set($src$$constant, reg_to_register_object($rd$$reg)); | 2476 __ set($src$$constant, reg_to_register_object($rd$$reg)); |
2412 %} | |
2413 | |
2414 enc_class SetNull( iRegI rd ) %{ | |
2415 emit3_simm13( cbuf, Assembler::arith_op, $rd$$reg, Assembler::or_op3, 0, 0 ); | |
2416 %} | 2477 %} |
2417 | 2478 |
2418 enc_class call_epilog %{ | 2479 enc_class call_epilog %{ |
2419 if( VerifyStackAtCalls ) { | 2480 if( VerifyStackAtCalls ) { |
2420 MacroAssembler _masm(&cbuf); | 2481 MacroAssembler _masm(&cbuf); |
2774 FloatRegister Fsrc2 = $primary ? reg_to_SingleFloatRegister_object($src2$$reg) | 2835 FloatRegister Fsrc2 = $primary ? reg_to_SingleFloatRegister_object($src2$$reg) |
2775 : reg_to_DoubleFloatRegister_object($src2$$reg); | 2836 : reg_to_DoubleFloatRegister_object($src2$$reg); |
2776 | 2837 |
2777 // Convert condition code fcc0 into -1,0,1; unordered reports less-than (-1) | 2838 // Convert condition code fcc0 into -1,0,1; unordered reports less-than (-1) |
2778 __ float_cmp( $primary, -1, Fsrc1, Fsrc2, Rdst); | 2839 __ float_cmp( $primary, -1, Fsrc1, Fsrc2, Rdst); |
2779 %} | |
2780 | |
2781 enc_class LdImmL (immL src, iRegL dst, o7RegL tmp) %{ // Load Immediate | |
2782 MacroAssembler _masm(&cbuf); | |
2783 Register dest = reg_to_register_object($dst$$reg); | |
2784 Register temp = reg_to_register_object($tmp$$reg); | |
2785 __ set64( $src$$constant, dest, temp ); | |
2786 %} | |
2787 | |
2788 enc_class LdReplImmI(immI src, regD dst, o7RegP tmp, int count, int width) %{ | |
2789 // Load a constant replicated "count" times with width "width" | |
2790 int bit_width = $width$$constant * 8; | |
2791 jlong elt_val = $src$$constant; | |
2792 elt_val &= (((jlong)1) << bit_width) - 1; // mask off sign bits | |
2793 jlong val = elt_val; | |
2794 for (int i = 0; i < $count$$constant - 1; i++) { | |
2795 val <<= bit_width; | |
2796 val |= elt_val; | |
2797 } | |
2798 jdouble dval = *(jdouble*)&val; // coerce to double type | |
2799 MacroAssembler _masm(&cbuf); | |
2800 address double_address = __ double_constant(dval); | |
2801 RelocationHolder rspec = internal_word_Relocation::spec(double_address); | |
2802 AddressLiteral addrlit(double_address, rspec); | |
2803 | |
2804 __ sethi(addrlit, $tmp$$Register); | |
2805 // XXX This is a quick fix for 6833573. | |
2806 //__ ldf(FloatRegisterImpl::D, $tmp$$Register, addrlit.low10(), $dst$$FloatRegister, rspec); | |
2807 __ ldf(FloatRegisterImpl::D, $tmp$$Register, addrlit.low10(), as_DoubleFloatRegister($dst$$reg), rspec); | |
2808 %} | 2840 %} |
2809 | 2841 |
2810 // Compiler ensures base is doubleword aligned and cnt is count of doublewords | 2842 // Compiler ensures base is doubleword aligned and cnt is count of doublewords |
2811 enc_class enc_Clear_Array(iRegX cnt, iRegP base, iRegX temp) %{ | 2843 enc_class enc_Clear_Array(iRegX cnt, iRegP base, iRegX temp) %{ |
2812 MacroAssembler _masm(&cbuf); | 2844 MacroAssembler _masm(&cbuf); |
3519 // formats are generated automatically for constants and base registers | 3551 // formats are generated automatically for constants and base registers |
3520 format %{ %} | 3552 format %{ %} |
3521 interface(CONST_INTER); | 3553 interface(CONST_INTER); |
3522 %} | 3554 %} |
3523 | 3555 |
3556 // Pointer Immediate: 32 or 64-bit | |
3557 operand immP_set() %{ | |
3558 predicate(!VM_Version::is_niagara1_plus()); | |
3559 match(ConP); | |
3560 | |
3561 op_cost(5); | |
3562 // formats are generated automatically for constants and base registers | |
3563 format %{ %} | |
3564 interface(CONST_INTER); | |
3565 %} | |
3566 | |
3567 // Pointer Immediate: 32 or 64-bit | |
3568 // From Niagara2 processors on a load should be better than materializing. | |
3569 operand immP_load() %{ | |
3570 predicate(VM_Version::is_niagara1_plus()); | |
3571 match(ConP); | |
3572 | |
3573 op_cost(5); | |
3574 // formats are generated automatically for constants and base registers | |
3575 format %{ %} | |
3576 interface(CONST_INTER); | |
3577 %} | |
3578 | |
3524 operand immP13() %{ | 3579 operand immP13() %{ |
3525 predicate((-4096 < n->get_ptr()) && (n->get_ptr() <= 4095)); | 3580 predicate((-4096 < n->get_ptr()) && (n->get_ptr() <= 4095)); |
3526 match(ConP); | 3581 match(ConP); |
3527 op_cost(0); | 3582 op_cost(0); |
3528 | 3583 |
3607 %} | 3662 %} |
3608 | 3663 |
3609 // Long Immediate: low 32-bit mask | 3664 // Long Immediate: low 32-bit mask |
3610 operand immL_32bits() %{ | 3665 operand immL_32bits() %{ |
3611 predicate(n->get_long() == 0xFFFFFFFFL); | 3666 predicate(n->get_long() == 0xFFFFFFFFL); |
3667 match(ConL); | |
3668 op_cost(0); | |
3669 | |
3670 format %{ %} | |
3671 interface(CONST_INTER); | |
3672 %} | |
3673 | |
3674 // Long Immediate: cheap (materialize in <= 3 instructions) | |
3675 operand immL_cheap() %{ | |
3676 predicate(!VM_Version::is_niagara1_plus() || MacroAssembler::size_of_set64(n->get_long()) <= 3); | |
3677 match(ConL); | |
3678 op_cost(0); | |
3679 | |
3680 format %{ %} | |
3681 interface(CONST_INTER); | |
3682 %} | |
3683 | |
3684 // Long Immediate: expensive (materialize in > 3 instructions) | |
3685 operand immL_expensive() %{ | |
3686 predicate(VM_Version::is_niagara1_plus() && MacroAssembler::size_of_set64(n->get_long()) > 3); | |
3612 match(ConL); | 3687 match(ConL); |
3613 op_cost(0); | 3688 op_cost(0); |
3614 | 3689 |
3615 format %{ %} | 3690 format %{ %} |
3616 interface(CONST_INTER); | 3691 interface(CONST_INTER); |
5979 format %{ "MOV $src,$dst" %} | 6054 format %{ "MOV $src,$dst" %} |
5980 ins_encode( Set13( src, dst ) ); | 6055 ins_encode( Set13( src, dst ) ); |
5981 ins_pipe(ialu_imm); | 6056 ins_pipe(ialu_imm); |
5982 %} | 6057 %} |
5983 | 6058 |
5984 instruct loadConP(iRegP dst, immP src) %{ | 6059 #ifndef _LP64 |
5985 match(Set dst src); | 6060 instruct loadConP(iRegP dst, immP con) %{ |
6061 match(Set dst con); | |
5986 ins_cost(DEFAULT_COST * 3/2); | 6062 ins_cost(DEFAULT_COST * 3/2); |
5987 format %{ "SET $src,$dst\t!ptr" %} | 6063 format %{ "SET $con,$dst\t!ptr" %} |
5988 // This rule does not use "expand" unlike loadConI because then | 6064 ins_encode %{ |
5989 // the result type is not known to be an Oop. An ADLC | 6065 // [RGV] This next line should be generated from ADLC |
5990 // enhancement will be needed to make that work - not worth it! | 6066 if (_opnds[1]->constant_is_oop()) { |
5991 | 6067 intptr_t val = $con$$constant; |
5992 ins_encode( SetPtr( src, dst ) ); | 6068 __ set_oop_constant((jobject) val, $dst$$Register); |
6069 } else { // non-oop pointers, e.g. card mark base, heap top | |
6070 __ set($con$$constant, $dst$$Register); | |
6071 } | |
6072 %} | |
5993 ins_pipe(loadConP); | 6073 ins_pipe(loadConP); |
5994 | 6074 %} |
5995 %} | 6075 #else |
6076 instruct loadConP_set(iRegP dst, immP_set con) %{ | |
6077 match(Set dst con); | |
6078 ins_cost(DEFAULT_COST * 3/2); | |
6079 format %{ "SET $con,$dst\t! ptr" %} | |
6080 ins_encode %{ | |
6081 // [RGV] This next line should be generated from ADLC | |
6082 if (_opnds[1]->constant_is_oop()) { | |
6083 intptr_t val = $con$$constant; | |
6084 __ set_oop_constant((jobject) val, $dst$$Register); | |
6085 } else { // non-oop pointers, e.g. card mark base, heap top | |
6086 __ set($con$$constant, $dst$$Register); | |
6087 } | |
6088 %} | |
6089 ins_pipe(loadConP); | |
6090 %} | |
6091 | |
6092 instruct loadConP_load(iRegP dst, immP_load con) %{ | |
6093 match(Set dst con); | |
6094 ins_cost(MEMORY_REF_COST); | |
6095 format %{ "LD [$constanttablebase + $constantoffset],$dst\t! load from constant table: ptr=$con" %} | |
6096 ins_encode %{ | |
6097 __ ld_ptr($constanttablebase, $constantoffset($con), $dst$$Register); | |
6098 %} | |
6099 ins_pipe(loadConP); | |
6100 %} | |
6101 #endif // _LP64 | |
5996 | 6102 |
5997 instruct loadConP0(iRegP dst, immP0 src) %{ | 6103 instruct loadConP0(iRegP dst, immP0 src) %{ |
5998 match(Set dst src); | 6104 match(Set dst src); |
5999 | 6105 |
6000 size(4); | 6106 size(4); |
6001 format %{ "CLR $dst\t!ptr" %} | 6107 format %{ "CLR $dst\t!ptr" %} |
6002 ins_encode( SetNull( dst ) ); | 6108 ins_encode %{ |
6109 __ clr($dst$$Register); | |
6110 %} | |
6003 ins_pipe(ialu_imm); | 6111 ins_pipe(ialu_imm); |
6004 %} | 6112 %} |
6005 | 6113 |
6006 instruct loadConP_poll(iRegP dst, immP_poll src) %{ | 6114 instruct loadConP_poll(iRegP dst, immP_poll src) %{ |
6007 match(Set dst src); | 6115 match(Set dst src); |
6017 instruct loadConN0(iRegN dst, immN0 src) %{ | 6125 instruct loadConN0(iRegN dst, immN0 src) %{ |
6018 match(Set dst src); | 6126 match(Set dst src); |
6019 | 6127 |
6020 size(4); | 6128 size(4); |
6021 format %{ "CLR $dst\t! compressed NULL ptr" %} | 6129 format %{ "CLR $dst\t! compressed NULL ptr" %} |
6022 ins_encode( SetNull( dst ) ); | 6130 ins_encode %{ |
6131 __ clr($dst$$Register); | |
6132 %} | |
6023 ins_pipe(ialu_imm); | 6133 ins_pipe(ialu_imm); |
6024 %} | 6134 %} |
6025 | 6135 |
6026 instruct loadConN(iRegN dst, immN src) %{ | 6136 instruct loadConN(iRegN dst, immN src) %{ |
6027 match(Set dst src); | 6137 match(Set dst src); |
6032 __ set_narrow_oop((jobject)$src$$constant, dst); | 6142 __ set_narrow_oop((jobject)$src$$constant, dst); |
6033 %} | 6143 %} |
6034 ins_pipe(ialu_hi_lo_reg); | 6144 ins_pipe(ialu_hi_lo_reg); |
6035 %} | 6145 %} |
6036 | 6146 |
6037 instruct loadConL(iRegL dst, immL src, o7RegL tmp) %{ | 6147 // Materialize long value (predicated by immL_cheap). |
6038 // %%% maybe this should work like loadConD | 6148 instruct loadConL_set64(iRegL dst, immL_cheap con, o7RegL tmp) %{ |
6039 match(Set dst src); | 6149 match(Set dst con); |
6040 effect(KILL tmp); | 6150 effect(KILL tmp); |
6041 ins_cost(DEFAULT_COST * 4); | 6151 ins_cost(DEFAULT_COST * 3); |
6042 format %{ "SET64 $src,$dst KILL $tmp\t! long" %} | 6152 format %{ "SET64 $con,$dst KILL $tmp\t! cheap long" %} |
6043 ins_encode( LdImmL(src, dst, tmp) ); | 6153 ins_encode %{ |
6154 __ set64($con$$constant, $dst$$Register, $tmp$$Register); | |
6155 %} | |
6156 ins_pipe(loadConL); | |
6157 %} | |
6158 | |
6159 // Load long value from constant table (predicated by immL_expensive). | |
6160 instruct loadConL_ldx(iRegL dst, immL_expensive con) %{ | |
6161 match(Set dst con); | |
6162 ins_cost(MEMORY_REF_COST); | |
6163 format %{ "LDX [$constanttablebase + $constantoffset],$dst\t! load from constant table: long=$con" %} | |
6164 ins_encode %{ | |
6165 __ ldx($constanttablebase, $constantoffset($con), $dst$$Register); | |
6166 %} | |
6044 ins_pipe(loadConL); | 6167 ins_pipe(loadConL); |
6045 %} | 6168 %} |
6046 | 6169 |
6047 instruct loadConL0( iRegL dst, immL0 src ) %{ | 6170 instruct loadConL0( iRegL dst, immL0 src ) %{ |
6048 match(Set dst src); | 6171 match(Set dst src); |
6061 format %{ "MOV $src,$dst\t! long" %} | 6184 format %{ "MOV $src,$dst\t! long" %} |
6062 ins_encode( Set13( src, dst ) ); | 6185 ins_encode( Set13( src, dst ) ); |
6063 ins_pipe(ialu_imm); | 6186 ins_pipe(ialu_imm); |
6064 %} | 6187 %} |
6065 | 6188 |
6066 instruct loadConF(regF dst, immF src, o7RegP tmp) %{ | 6189 instruct loadConF(regF dst, immF con) %{ |
6067 match(Set dst src); | 6190 match(Set dst con); |
6068 effect(KILL tmp); | 6191 size(4); |
6069 | 6192 format %{ "LDF [$constanttablebase + $constantoffset],$dst\t! load from constant table: float=$con" %} |
6070 #ifdef _LP64 | |
6071 size(8*4); | |
6072 #else | |
6073 size(2*4); | |
6074 #endif | |
6075 | |
6076 format %{ "SETHI hi(&$src),$tmp\t!get float $src from table\n\t" | |
6077 "LDF [$tmp+lo(&$src)],$dst" %} | |
6078 ins_encode %{ | 6193 ins_encode %{ |
6079 address float_address = __ float_constant($src$$constant); | 6194 __ ldf(FloatRegisterImpl::S, $constanttablebase, $constantoffset($con), $dst$$FloatRegister); |
6080 RelocationHolder rspec = internal_word_Relocation::spec(float_address); | |
6081 AddressLiteral addrlit(float_address, rspec); | |
6082 | |
6083 __ sethi(addrlit, $tmp$$Register); | |
6084 __ ldf(FloatRegisterImpl::S, $tmp$$Register, addrlit.low10(), $dst$$FloatRegister, rspec); | |
6085 %} | 6195 %} |
6086 ins_pipe(loadConFD); | 6196 ins_pipe(loadConFD); |
6087 %} | 6197 %} |
6088 | 6198 |
6089 instruct loadConD(regD dst, immD src, o7RegP tmp) %{ | 6199 instruct loadConD(regD dst, immD con) %{ |
6090 match(Set dst src); | 6200 match(Set dst con); |
6091 effect(KILL tmp); | 6201 size(4); |
6092 | 6202 format %{ "LDDF [$constanttablebase + $constantoffset],$dst\t! load from constant table: double=$con" %} |
6093 #ifdef _LP64 | |
6094 size(8*4); | |
6095 #else | |
6096 size(2*4); | |
6097 #endif | |
6098 | |
6099 format %{ "SETHI hi(&$src),$tmp\t!get double $src from table\n\t" | |
6100 "LDDF [$tmp+lo(&$src)],$dst" %} | |
6101 ins_encode %{ | 6203 ins_encode %{ |
6102 address double_address = __ double_constant($src$$constant); | |
6103 RelocationHolder rspec = internal_word_Relocation::spec(double_address); | |
6104 AddressLiteral addrlit(double_address, rspec); | |
6105 | |
6106 __ sethi(addrlit, $tmp$$Register); | |
6107 // XXX This is a quick fix for 6833573. | 6204 // XXX This is a quick fix for 6833573. |
6108 //__ ldf(FloatRegisterImpl::D, $tmp$$Register, addrlit.low10(), $dst$$FloatRegister, rspec); | 6205 //__ ldf(FloatRegisterImpl::D, $constanttablebase, $constantoffset($con), $dst$$FloatRegister); |
6109 __ ldf(FloatRegisterImpl::D, $tmp$$Register, addrlit.low10(), as_DoubleFloatRegister($dst$$reg), rspec); | 6206 __ ldf(FloatRegisterImpl::D, $constanttablebase, $constantoffset($con), as_DoubleFloatRegister($dst$$reg)); |
6110 %} | 6207 %} |
6111 ins_pipe(loadConFD); | 6208 ins_pipe(loadConFD); |
6112 %} | 6209 %} |
6113 | 6210 |
6114 // Prefetch instructions. | 6211 // Prefetch instructions. |
8556 regL_to_stkD(dst, tmp); | 8653 regL_to_stkD(dst, tmp); |
8557 %} | 8654 %} |
8558 %} | 8655 %} |
8559 | 8656 |
8560 // Replicate scalar constant to packed byte values in Double register | 8657 // Replicate scalar constant to packed byte values in Double register |
8561 instruct Repl8B_immI(regD dst, immI13 src, o7RegP tmp) %{ | 8658 instruct Repl8B_immI(regD dst, immI13 con) %{ |
8562 match(Set dst (Replicate8B src)); | 8659 match(Set dst (Replicate8B con)); |
8563 #ifdef _LP64 | 8660 size(4); |
8564 size(36); | 8661 format %{ "LDDF [$constanttablebase + $constantoffset],$dst\t! load from constant table: Repl8B($con)" %} |
8565 #else | 8662 ins_encode %{ |
8566 size(8); | 8663 // XXX This is a quick fix for 6833573. |
8567 #endif | 8664 //__ ldf(FloatRegisterImpl::D, $constanttablebase, $constantoffset(replicate_immI($con$$constant, 8, 1)), $dst$$FloatRegister); |
8568 format %{ "SETHI hi(&Repl8($src)),$tmp\t!get Repl8B($src) from table\n\t" | 8665 __ ldf(FloatRegisterImpl::D, $constanttablebase, $constantoffset(replicate_immI($con$$constant, 8, 1)), as_DoubleFloatRegister($dst$$reg)); |
8569 "LDDF [$tmp+lo(&Repl8($src))],$dst" %} | 8666 %} |
8570 ins_encode( LdReplImmI(src, dst, tmp, (8), (1)) ); | |
8571 ins_pipe(loadConFD); | 8667 ins_pipe(loadConFD); |
8572 %} | 8668 %} |
8573 | 8669 |
8574 // Replicate scalar to packed char values into stack slot | 8670 // Replicate scalar to packed char values into stack slot |
8575 instruct Repl4C_reg_helper(iRegL dst, iRegI src) %{ | 8671 instruct Repl4C_reg_helper(iRegL dst, iRegI src) %{ |
8592 regL_to_stkD(dst, tmp); | 8688 regL_to_stkD(dst, tmp); |
8593 %} | 8689 %} |
8594 %} | 8690 %} |
8595 | 8691 |
8596 // Replicate scalar constant to packed char values in Double register | 8692 // Replicate scalar constant to packed char values in Double register |
8597 instruct Repl4C_immI(regD dst, immI src, o7RegP tmp) %{ | 8693 instruct Repl4C_immI(regD dst, immI con) %{ |
8598 match(Set dst (Replicate4C src)); | 8694 match(Set dst (Replicate4C con)); |
8599 #ifdef _LP64 | 8695 size(4); |
8600 size(36); | 8696 format %{ "LDDF [$constanttablebase + $constantoffset],$dst\t! load from constant table: Repl4C($con)" %} |
8601 #else | 8697 ins_encode %{ |
8602 size(8); | 8698 // XXX This is a quick fix for 6833573. |
8603 #endif | 8699 //__ ldf(FloatRegisterImpl::D, $constanttablebase, $constantoffset(replicate_immI($con$$constant, 4, 2)), $dst$$FloatRegister); |
8604 format %{ "SETHI hi(&Repl4($src)),$tmp\t!get Repl4C($src) from table\n\t" | 8700 __ ldf(FloatRegisterImpl::D, $constanttablebase, $constantoffset(replicate_immI($con$$constant, 4, 2)), as_DoubleFloatRegister($dst$$reg)); |
8605 "LDDF [$tmp+lo(&Repl4($src))],$dst" %} | 8701 %} |
8606 ins_encode( LdReplImmI(src, dst, tmp, (4), (2)) ); | |
8607 ins_pipe(loadConFD); | 8702 ins_pipe(loadConFD); |
8608 %} | 8703 %} |
8609 | 8704 |
8610 // Replicate scalar to packed short values into stack slot | 8705 // Replicate scalar to packed short values into stack slot |
8611 instruct Repl4S_reg_helper(iRegL dst, iRegI src) %{ | 8706 instruct Repl4S_reg_helper(iRegL dst, iRegI src) %{ |
8628 regL_to_stkD(dst, tmp); | 8723 regL_to_stkD(dst, tmp); |
8629 %} | 8724 %} |
8630 %} | 8725 %} |
8631 | 8726 |
8632 // Replicate scalar constant to packed short values in Double register | 8727 // Replicate scalar constant to packed short values in Double register |
8633 instruct Repl4S_immI(regD dst, immI src, o7RegP tmp) %{ | 8728 instruct Repl4S_immI(regD dst, immI con) %{ |
8634 match(Set dst (Replicate4S src)); | 8729 match(Set dst (Replicate4S con)); |
8635 #ifdef _LP64 | 8730 size(4); |
8636 size(36); | 8731 format %{ "LDDF [$constanttablebase + $constantoffset],$dst\t! load from constant table: Repl4S($con)" %} |
8637 #else | 8732 ins_encode %{ |
8638 size(8); | 8733 // XXX This is a quick fix for 6833573. |
8639 #endif | 8734 //__ ldf(FloatRegisterImpl::D, $constanttablebase, $constantoffset(replicate_immI($con$$constant, 4, 2)), $dst$$FloatRegister); |
8640 format %{ "SETHI hi(&Repl4($src)),$tmp\t!get Repl4S($src) from table\n\t" | 8735 __ ldf(FloatRegisterImpl::D, $constanttablebase, $constantoffset(replicate_immI($con$$constant, 4, 2)), as_DoubleFloatRegister($dst$$reg)); |
8641 "LDDF [$tmp+lo(&Repl4($src))],$dst" %} | 8736 %} |
8642 ins_encode( LdReplImmI(src, dst, tmp, (4), (2)) ); | |
8643 ins_pipe(loadConFD); | 8737 ins_pipe(loadConFD); |
8644 %} | 8738 %} |
8645 | 8739 |
8646 // Replicate scalar to packed int values in Double register | 8740 // Replicate scalar to packed int values in Double register |
8647 instruct Repl2I_reg_helper(iRegL dst, iRegI src) %{ | 8741 instruct Repl2I_reg_helper(iRegL dst, iRegI src) %{ |
8662 regL_to_stkD(dst, tmp); | 8756 regL_to_stkD(dst, tmp); |
8663 %} | 8757 %} |
8664 %} | 8758 %} |
8665 | 8759 |
8666 // Replicate scalar zero constant to packed int values in Double register | 8760 // Replicate scalar zero constant to packed int values in Double register |
8667 instruct Repl2I_immI(regD dst, immI src, o7RegP tmp) %{ | 8761 instruct Repl2I_immI(regD dst, immI con) %{ |
8668 match(Set dst (Replicate2I src)); | 8762 match(Set dst (Replicate2I con)); |
8669 #ifdef _LP64 | 8763 size(4); |
8670 size(36); | 8764 format %{ "LDDF [$constanttablebase + $constantoffset],$dst\t! load from constant table: Repl2I($con)" %} |
8671 #else | 8765 ins_encode %{ |
8672 size(8); | 8766 // XXX This is a quick fix for 6833573. |
8673 #endif | 8767 //__ ldf(FloatRegisterImpl::D, $constanttablebase, $constantoffset(replicate_immI($con$$constant, 2, 4)), $dst$$FloatRegister); |
8674 format %{ "SETHI hi(&Repl2($src)),$tmp\t!get Repl2I($src) from table\n\t" | 8768 __ ldf(FloatRegisterImpl::D, $constanttablebase, $constantoffset(replicate_immI($con$$constant, 2, 4)), as_DoubleFloatRegister($dst$$reg)); |
8675 "LDDF [$tmp+lo(&Repl2($src))],$dst" %} | 8769 %} |
8676 ins_encode( LdReplImmI(src, dst, tmp, (2), (4)) ); | |
8677 ins_pipe(loadConFD); | 8770 ins_pipe(loadConFD); |
8678 %} | 8771 %} |
8679 | 8772 |
8680 //----------Control Flow Instructions------------------------------------------ | 8773 //----------Control Flow Instructions------------------------------------------ |
8681 // Compare Instructions | 8774 // Compare Instructions |
8927 instruct jumpXtnd(iRegX switch_val, o7RegI table) %{ | 9020 instruct jumpXtnd(iRegX switch_val, o7RegI table) %{ |
8928 match(Jump switch_val); | 9021 match(Jump switch_val); |
8929 | 9022 |
8930 ins_cost(350); | 9023 ins_cost(350); |
8931 | 9024 |
8932 format %{ "SETHI [hi(table_base)],O7\n\t" | 9025 format %{ "ADD $constanttablebase, $constantoffset, O7\n\t" |
8933 "ADD O7, lo(table_base), O7\n\t" | 9026 "LD [O7 + $switch_val], O7\n\t" |
8934 "LD [O7+$switch_val], O7\n\t" | |
8935 "JUMP O7" | 9027 "JUMP O7" |
8936 %} | 9028 %} |
8937 ins_encode( jump_enc( switch_val, table) ); | 9029 ins_encode %{ |
9030 // Calculate table address into a register. | |
9031 Register table_reg; | |
9032 Register label_reg = O7; | |
9033 if (constant_offset() == 0) { | |
9034 table_reg = $constanttablebase; | |
9035 } else { | |
9036 table_reg = O7; | |
9037 __ add($constanttablebase, $constantoffset, table_reg); | |
9038 } | |
9039 | |
9040 // Jump to base address + switch value | |
9041 __ ld_ptr(table_reg, $switch_val$$Register, label_reg); | |
9042 __ jmp(label_reg, G0); | |
9043 __ delayed()->nop(); | |
9044 %} | |
8938 ins_pc_relative(1); | 9045 ins_pc_relative(1); |
8939 ins_pipe(ialu_reg_reg); | 9046 ins_pipe(ialu_reg_reg); |
8940 %} | 9047 %} |
8941 | 9048 |
8942 // Direct Branch. Use V8 version with longer range. | 9049 // Direct Branch. Use V8 version with longer range. |