Mercurial > hg > truffle
comparison src/cpu/x86/vm/x86_64.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 | ae065c367d93 |
children | 6bbaedb03534 |
comparison
equal
deleted
inserted
replaced
2007:5ddfcf4b079e | 2008:2f644f85485d |
---|---|
828 MacroAssembler _masm(&cbuf); | 828 MacroAssembler _masm(&cbuf); |
829 | 829 |
830 __ movdqa(as_XMMRegister(dst_encoding), as_XMMRegister(src_encoding)); | 830 __ movdqa(as_XMMRegister(dst_encoding), as_XMMRegister(src_encoding)); |
831 } | 831 } |
832 } | 832 } |
833 | |
834 | |
835 //============================================================================= | |
836 const bool Matcher::constant_table_absolute_addressing = true; | |
837 const RegMask& MachConstantBaseNode::_out_RegMask = RegMask::Empty; | |
838 | |
839 void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const { | |
840 // Empty encoding | |
841 } | |
842 | |
843 uint MachConstantBaseNode::size(PhaseRegAlloc* ra_) const { | |
844 return 0; | |
845 } | |
846 | |
847 #ifndef PRODUCT | |
848 void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const { | |
849 st->print("# MachConstantBaseNode (empty encoding)"); | |
850 } | |
851 #endif | |
833 | 852 |
834 | 853 |
835 //============================================================================= | 854 //============================================================================= |
836 #ifndef PRODUCT | 855 #ifndef PRODUCT |
837 void MachPrologNode::format(PhaseRegAlloc* ra_, outputStream* st) const | 856 void MachPrologNode::format(PhaseRegAlloc* ra_, outputStream* st) const |
1920 assert(__ offset() - offset <= (int) size_deopt_handler(), "overflow"); | 1939 assert(__ offset() - offset <= (int) size_deopt_handler(), "overflow"); |
1921 __ end_a_stub(); | 1940 __ end_a_stub(); |
1922 return offset; | 1941 return offset; |
1923 } | 1942 } |
1924 | 1943 |
1925 static void emit_double_constant(CodeBuffer& cbuf, double x) { | |
1926 int mark = cbuf.insts()->mark_off(); | |
1927 MacroAssembler _masm(&cbuf); | |
1928 address double_address = __ double_constant(x); | |
1929 cbuf.insts()->set_mark_off(mark); // preserve mark across masm shift | |
1930 emit_d32_reloc(cbuf, | |
1931 (int) (double_address - cbuf.insts_end() - 4), | |
1932 internal_word_Relocation::spec(double_address), | |
1933 RELOC_DISP32); | |
1934 } | |
1935 | |
1936 static void emit_float_constant(CodeBuffer& cbuf, float x) { | |
1937 int mark = cbuf.insts()->mark_off(); | |
1938 MacroAssembler _masm(&cbuf); | |
1939 address float_address = __ float_constant(x); | |
1940 cbuf.insts()->set_mark_off(mark); // preserve mark across masm shift | |
1941 emit_d32_reloc(cbuf, | |
1942 (int) (float_address - cbuf.insts_end() - 4), | |
1943 internal_word_Relocation::spec(float_address), | |
1944 RELOC_DISP32); | |
1945 } | |
1946 | |
1947 | 1944 |
1948 const bool Matcher::match_rule_supported(int opcode) { | 1945 const bool Matcher::match_rule_supported(int opcode) { |
1949 if (!has_match_rule(opcode)) | 1946 if (!has_match_rule(opcode)) |
1950 return false; | 1947 return false; |
1951 | 1948 |
2787 } else { | 2784 } else { |
2788 emit_d64(cbuf, $src$$constant); | 2785 emit_d64(cbuf, $src$$constant); |
2789 } | 2786 } |
2790 %} | 2787 %} |
2791 | 2788 |
2792 enc_class load_immF(regF dst, immF con) | |
2793 %{ | |
2794 // XXX reg_mem doesn't support RIP-relative addressing yet | |
2795 emit_rm(cbuf, 0x0, $dst$$reg & 7, 0x5); // 00 reg 101 | |
2796 emit_float_constant(cbuf, $con$$constant); | |
2797 %} | |
2798 | |
2799 enc_class load_immD(regD dst, immD con) | |
2800 %{ | |
2801 // XXX reg_mem doesn't support RIP-relative addressing yet | |
2802 emit_rm(cbuf, 0x0, $dst$$reg & 7, 0x5); // 00 reg 101 | |
2803 emit_double_constant(cbuf, $con$$constant); | |
2804 %} | |
2805 | |
2806 enc_class load_conF (regF dst, immF con) %{ // Load float constant | |
2807 emit_opcode(cbuf, 0xF3); | |
2808 if ($dst$$reg >= 8) { | |
2809 emit_opcode(cbuf, Assembler::REX_R); | |
2810 } | |
2811 emit_opcode(cbuf, 0x0F); | |
2812 emit_opcode(cbuf, 0x10); | |
2813 emit_rm(cbuf, 0x0, $dst$$reg & 7, 0x5); // 00 reg 101 | |
2814 emit_float_constant(cbuf, $con$$constant); | |
2815 %} | |
2816 | |
2817 enc_class load_conD (regD dst, immD con) %{ // Load double constant | |
2818 // UseXmmLoadAndClearUpper ? movsd(dst, con) : movlpd(dst, con) | |
2819 emit_opcode(cbuf, UseXmmLoadAndClearUpper ? 0xF2 : 0x66); | |
2820 if ($dst$$reg >= 8) { | |
2821 emit_opcode(cbuf, Assembler::REX_R); | |
2822 } | |
2823 emit_opcode(cbuf, 0x0F); | |
2824 emit_opcode(cbuf, UseXmmLoadAndClearUpper ? 0x10 : 0x12); | |
2825 emit_rm(cbuf, 0x0, $dst$$reg & 7, 0x5); // 00 reg 101 | |
2826 emit_double_constant(cbuf, $con$$constant); | |
2827 %} | |
2828 | |
2829 // Encode a reg-reg copy. If it is useless, then empty encoding. | 2789 // Encode a reg-reg copy. If it is useless, then empty encoding. |
2830 enc_class enc_copy(rRegI dst, rRegI src) | 2790 enc_class enc_copy(rRegI dst, rRegI src) |
2831 %{ | 2791 %{ |
2832 encode_copy(cbuf, $dst$$reg, $src$$reg); | 2792 encode_copy(cbuf, $dst$$reg, $src$$reg); |
2833 %} | 2793 %} |
2922 | 2882 |
2923 enc_class conmemref (rRegP t1) %{ // Con32(storeImmI) | 2883 enc_class conmemref (rRegP t1) %{ // Con32(storeImmI) |
2924 // Output immediate memory reference | 2884 // Output immediate memory reference |
2925 emit_rm(cbuf, 0x00, $t1$$reg, 0x05 ); | 2885 emit_rm(cbuf, 0x00, $t1$$reg, 0x05 ); |
2926 emit_d32(cbuf, 0x00); | 2886 emit_d32(cbuf, 0x00); |
2927 %} | |
2928 | |
2929 enc_class jump_enc(rRegL switch_val, rRegI dest) %{ | |
2930 MacroAssembler masm(&cbuf); | |
2931 | |
2932 Register switch_reg = as_Register($switch_val$$reg); | |
2933 Register dest_reg = as_Register($dest$$reg); | |
2934 address table_base = masm.address_table_constant(_index2label); | |
2935 | |
2936 // We could use jump(ArrayAddress) except that the macro assembler needs to use r10 | |
2937 // to do that and the compiler is using that register as one it can allocate. | |
2938 // So we build it all by hand. | |
2939 // Address index(noreg, switch_reg, Address::times_1); | |
2940 // ArrayAddress dispatch(table, index); | |
2941 | |
2942 Address dispatch(dest_reg, switch_reg, Address::times_1); | |
2943 | |
2944 masm.lea(dest_reg, InternalAddress(table_base)); | |
2945 masm.jmp(dispatch); | |
2946 %} | |
2947 | |
2948 enc_class jump_enc_addr(rRegL switch_val, immI2 shift, immL32 offset, rRegI dest) %{ | |
2949 MacroAssembler masm(&cbuf); | |
2950 | |
2951 Register switch_reg = as_Register($switch_val$$reg); | |
2952 Register dest_reg = as_Register($dest$$reg); | |
2953 address table_base = masm.address_table_constant(_index2label); | |
2954 | |
2955 // We could use jump(ArrayAddress) except that the macro assembler needs to use r10 | |
2956 // to do that and the compiler is using that register as one it can allocate. | |
2957 // So we build it all by hand. | |
2958 // Address index(noreg, switch_reg, (Address::ScaleFactor)$shift$$constant, (int)$offset$$constant); | |
2959 // ArrayAddress dispatch(table, index); | |
2960 | |
2961 Address dispatch(dest_reg, switch_reg, (Address::ScaleFactor)$shift$$constant, (int)$offset$$constant); | |
2962 | |
2963 masm.lea(dest_reg, InternalAddress(table_base)); | |
2964 masm.jmp(dispatch); | |
2965 %} | |
2966 | |
2967 enc_class jump_enc_offset(rRegL switch_val, immI2 shift, rRegI dest) %{ | |
2968 MacroAssembler masm(&cbuf); | |
2969 | |
2970 Register switch_reg = as_Register($switch_val$$reg); | |
2971 Register dest_reg = as_Register($dest$$reg); | |
2972 address table_base = masm.address_table_constant(_index2label); | |
2973 | |
2974 // We could use jump(ArrayAddress) except that the macro assembler needs to use r10 | |
2975 // to do that and the compiler is using that register as one it can allocate. | |
2976 // So we build it all by hand. | |
2977 // Address index(noreg, switch_reg, (Address::ScaleFactor)$shift$$constant); | |
2978 // ArrayAddress dispatch(table, index); | |
2979 | |
2980 Address dispatch(dest_reg, switch_reg, (Address::ScaleFactor)$shift$$constant); | |
2981 masm.lea(dest_reg, InternalAddress(table_base)); | |
2982 masm.jmp(dispatch); | |
2983 | |
2984 %} | 2887 %} |
2985 | 2888 |
2986 enc_class lock_prefix() | 2889 enc_class lock_prefix() |
2987 %{ | 2890 %{ |
2988 if (os::is_MP()) { | 2891 if (os::is_MP()) { |
6639 format %{ "movq $dst, $src\t# long (32-bit)" %} | 6542 format %{ "movq $dst, $src\t# long (32-bit)" %} |
6640 ins_encode(load_immL32(dst, src)); | 6543 ins_encode(load_immL32(dst, src)); |
6641 ins_pipe(ialu_reg); | 6544 ins_pipe(ialu_reg); |
6642 %} | 6545 %} |
6643 | 6546 |
6644 instruct loadConP(rRegP dst, immP src) | 6547 instruct loadConP(rRegP dst, immP con) %{ |
6645 %{ | 6548 match(Set dst con); |
6646 match(Set dst src); | 6549 |
6647 | 6550 format %{ "movq $dst, $con\t# ptr" %} |
6648 format %{ "movq $dst, $src\t# ptr" %} | 6551 ins_encode(load_immP(dst, con)); |
6649 ins_encode(load_immP(dst, src)); | |
6650 ins_pipe(ialu_reg_fat); // XXX | 6552 ins_pipe(ialu_reg_fat); // XXX |
6651 %} | 6553 %} |
6652 | 6554 |
6653 instruct loadConP0(rRegP dst, immP0 src, rFlagsReg cr) | 6555 instruct loadConP0(rRegP dst, immP0 src, rFlagsReg cr) |
6654 %{ | 6556 %{ |
6671 format %{ "movl $dst, $src\t# ptr (positive 32-bit)" %} | 6573 format %{ "movl $dst, $src\t# ptr (positive 32-bit)" %} |
6672 ins_encode(load_immP31(dst, src)); | 6574 ins_encode(load_immP31(dst, src)); |
6673 ins_pipe(ialu_reg); | 6575 ins_pipe(ialu_reg); |
6674 %} | 6576 %} |
6675 | 6577 |
6676 instruct loadConF(regF dst, immF src) | 6578 instruct loadConF(regF dst, immF con) %{ |
6677 %{ | 6579 match(Set dst con); |
6678 match(Set dst src); | |
6679 ins_cost(125); | 6580 ins_cost(125); |
6680 | 6581 format %{ "movss $dst, [$constantaddress]\t# load from constant table: float=$con" %} |
6681 format %{ "movss $dst, [$src]" %} | 6582 ins_encode %{ |
6682 ins_encode(load_conF(dst, src)); | 6583 __ movflt($dst$$XMMRegister, $constantaddress($con)); |
6584 %} | |
6683 ins_pipe(pipe_slow); | 6585 ins_pipe(pipe_slow); |
6684 %} | 6586 %} |
6685 | 6587 |
6686 instruct loadConN0(rRegN dst, immN0 src, rFlagsReg cr) %{ | 6588 instruct loadConN0(rRegN dst, immN0 src, rFlagsReg cr) %{ |
6687 match(Set dst src); | 6589 match(Set dst src); |
6719 ins_encode(REX_reg_reg(dst, dst), OpcP, OpcS, reg_reg(dst, dst)); | 6621 ins_encode(REX_reg_reg(dst, dst), OpcP, OpcS, reg_reg(dst, dst)); |
6720 ins_pipe(pipe_slow); | 6622 ins_pipe(pipe_slow); |
6721 %} | 6623 %} |
6722 | 6624 |
6723 // Use the same format since predicate() can not be used here. | 6625 // Use the same format since predicate() can not be used here. |
6724 instruct loadConD(regD dst, immD src) | 6626 instruct loadConD(regD dst, immD con) %{ |
6725 %{ | 6627 match(Set dst con); |
6726 match(Set dst src); | |
6727 ins_cost(125); | 6628 ins_cost(125); |
6728 | 6629 format %{ "movsd $dst, [$constantaddress]\t# load from constant table: double=$con" %} |
6729 format %{ "movsd $dst, [$src]" %} | 6630 ins_encode %{ |
6730 ins_encode(load_conD(dst, src)); | 6631 __ movdbl($dst$$XMMRegister, $constantaddress($con)); |
6632 %} | |
6731 ins_pipe(pipe_slow); | 6633 ins_pipe(pipe_slow); |
6732 %} | 6634 %} |
6733 | 6635 |
6734 instruct loadConD0(regD dst, immD0 src) | 6636 instruct loadConD0(regD dst, immD0 src) |
6735 %{ | 6637 %{ |
7692 match(Jump (LShiftL switch_val shift)); | 7594 match(Jump (LShiftL switch_val shift)); |
7693 ins_cost(350); | 7595 ins_cost(350); |
7694 predicate(false); | 7596 predicate(false); |
7695 effect(TEMP dest); | 7597 effect(TEMP dest); |
7696 | 7598 |
7697 format %{ "leaq $dest, table_base\n\t" | 7599 format %{ "leaq $dest, [$constantaddress]\n\t" |
7698 "jmp [$dest + $switch_val << $shift]\n\t" %} | 7600 "jmp [$dest + $switch_val << $shift]\n\t" %} |
7699 ins_encode(jump_enc_offset(switch_val, shift, dest)); | 7601 ins_encode %{ |
7602 // We could use jump(ArrayAddress) except that the macro assembler needs to use r10 | |
7603 // to do that and the compiler is using that register as one it can allocate. | |
7604 // So we build it all by hand. | |
7605 // Address index(noreg, switch_reg, (Address::ScaleFactor)$shift$$constant); | |
7606 // ArrayAddress dispatch(table, index); | |
7607 Address dispatch($dest$$Register, $switch_val$$Register, (Address::ScaleFactor) $shift$$constant); | |
7608 __ lea($dest$$Register, $constantaddress); | |
7609 __ jmp(dispatch); | |
7610 %} | |
7700 ins_pipe(pipe_jmp); | 7611 ins_pipe(pipe_jmp); |
7701 ins_pc_relative(1); | 7612 ins_pc_relative(1); |
7702 %} | 7613 %} |
7703 | 7614 |
7704 instruct jumpXtnd_addr(rRegL switch_val, immI2 shift, immL32 offset, rRegI dest) %{ | 7615 instruct jumpXtnd_addr(rRegL switch_val, immI2 shift, immL32 offset, rRegI dest) %{ |
7705 match(Jump (AddL (LShiftL switch_val shift) offset)); | 7616 match(Jump (AddL (LShiftL switch_val shift) offset)); |
7706 ins_cost(350); | 7617 ins_cost(350); |
7707 effect(TEMP dest); | 7618 effect(TEMP dest); |
7708 | 7619 |
7709 format %{ "leaq $dest, table_base\n\t" | 7620 format %{ "leaq $dest, [$constantaddress]\n\t" |
7710 "jmp [$dest + $switch_val << $shift + $offset]\n\t" %} | 7621 "jmp [$dest + $switch_val << $shift + $offset]\n\t" %} |
7711 ins_encode(jump_enc_addr(switch_val, shift, offset, dest)); | 7622 ins_encode %{ |
7623 // We could use jump(ArrayAddress) except that the macro assembler needs to use r10 | |
7624 // to do that and the compiler is using that register as one it can allocate. | |
7625 // So we build it all by hand. | |
7626 // Address index(noreg, switch_reg, (Address::ScaleFactor) $shift$$constant, (int) $offset$$constant); | |
7627 // ArrayAddress dispatch(table, index); | |
7628 Address dispatch($dest$$Register, $switch_val$$Register, (Address::ScaleFactor) $shift$$constant, (int) $offset$$constant); | |
7629 __ lea($dest$$Register, $constantaddress); | |
7630 __ jmp(dispatch); | |
7631 %} | |
7712 ins_pipe(pipe_jmp); | 7632 ins_pipe(pipe_jmp); |
7713 ins_pc_relative(1); | 7633 ins_pc_relative(1); |
7714 %} | 7634 %} |
7715 | 7635 |
7716 instruct jumpXtnd(rRegL switch_val, rRegI dest) %{ | 7636 instruct jumpXtnd(rRegL switch_val, rRegI dest) %{ |
7717 match(Jump switch_val); | 7637 match(Jump switch_val); |
7718 ins_cost(350); | 7638 ins_cost(350); |
7719 effect(TEMP dest); | 7639 effect(TEMP dest); |
7720 | 7640 |
7721 format %{ "leaq $dest, table_base\n\t" | 7641 format %{ "leaq $dest, [$constantaddress]\n\t" |
7722 "jmp [$dest + $switch_val]\n\t" %} | 7642 "jmp [$dest + $switch_val]\n\t" %} |
7723 ins_encode(jump_enc(switch_val, dest)); | 7643 ins_encode %{ |
7644 // We could use jump(ArrayAddress) except that the macro assembler needs to use r10 | |
7645 // to do that and the compiler is using that register as one it can allocate. | |
7646 // So we build it all by hand. | |
7647 // Address index(noreg, switch_reg, Address::times_1); | |
7648 // ArrayAddress dispatch(table, index); | |
7649 Address dispatch($dest$$Register, $switch_val$$Register, Address::times_1); | |
7650 __ lea($dest$$Register, $constantaddress); | |
7651 __ jmp(dispatch); | |
7652 %} | |
7724 ins_pipe(pipe_jmp); | 7653 ins_pipe(pipe_jmp); |
7725 ins_pc_relative(1); | 7654 ins_pc_relative(1); |
7726 %} | 7655 %} |
7727 | 7656 |
7728 // Conditional move | 7657 // Conditional move |
10374 opcode(0x0F, 0x2E); | 10303 opcode(0x0F, 0x2E); |
10375 ins_encode(REX_reg_mem(src1, src2), OpcP, OpcS, reg_mem(src1, src2)); | 10304 ins_encode(REX_reg_mem(src1, src2), OpcP, OpcS, reg_mem(src1, src2)); |
10376 ins_pipe(pipe_slow); | 10305 ins_pipe(pipe_slow); |
10377 %} | 10306 %} |
10378 | 10307 |
10379 instruct cmpF_cc_imm(rFlagsRegU cr, regF src1, immF src2) | 10308 instruct cmpF_cc_imm(rFlagsRegU cr, regF src, immF con) %{ |
10380 %{ | 10309 match(Set cr (CmpF src con)); |
10381 match(Set cr (CmpF src1 src2)); | |
10382 | 10310 |
10383 ins_cost(145); | 10311 ins_cost(145); |
10384 format %{ "ucomiss $src1, $src2\n\t" | 10312 format %{ "ucomiss $src, [$constantaddress]\t# load from constant table: float=$con\n\t" |
10385 "jnp,s exit\n\t" | 10313 "jnp,s exit\n\t" |
10386 "pushfq\t# saw NaN, set CF\n\t" | 10314 "pushfq\t# saw NaN, set CF\n\t" |
10387 "andq [rsp], #0xffffff2b\n\t" | 10315 "andq [rsp], #0xffffff2b\n\t" |
10388 "popfq\n" | 10316 "popfq\n" |
10389 "exit: nop\t# avoid branch to branch" %} | 10317 "exit: nop\t# avoid branch to branch" %} |
10390 opcode(0x0F, 0x2E); | 10318 ins_encode %{ |
10391 ins_encode(REX_reg_mem(src1, src2), OpcP, OpcS, load_immF(src1, src2), | 10319 Label L_exit; |
10392 cmpfp_fixup); | 10320 __ ucomiss($src$$XMMRegister, $constantaddress($con)); |
10321 __ jcc(Assembler::noParity, L_exit); | |
10322 __ pushf(); | |
10323 __ andq(rsp, 0xffffff2b); | |
10324 __ popf(); | |
10325 __ bind(L_exit); | |
10326 __ nop(); | |
10327 %} | |
10393 ins_pipe(pipe_slow); | 10328 ins_pipe(pipe_slow); |
10394 %} | 10329 %} |
10395 | 10330 |
10396 instruct cmpF_cc_immCF(rFlagsRegUCF cr, regF src1, immF src2) %{ | 10331 instruct cmpF_cc_immCF(rFlagsRegUCF cr, regF src, immF con) %{ |
10397 match(Set cr (CmpF src1 src2)); | 10332 match(Set cr (CmpF src con)); |
10398 | |
10399 ins_cost(100); | 10333 ins_cost(100); |
10400 format %{ "ucomiss $src1, $src2" %} | 10334 format %{ "ucomiss $src, [$constantaddress]\t# load from constant table: float=$con" %} |
10401 opcode(0x0F, 0x2E); | 10335 ins_encode %{ |
10402 ins_encode(REX_reg_mem(src1, src2), OpcP, OpcS, load_immF(src1, src2)); | 10336 __ ucomiss($src$$XMMRegister, $constantaddress($con)); |
10337 %} | |
10403 ins_pipe(pipe_slow); | 10338 ins_pipe(pipe_slow); |
10404 %} | 10339 %} |
10405 | 10340 |
10406 instruct cmpD_cc_reg(rFlagsRegU cr, regD src1, regD src2) | 10341 instruct cmpD_cc_reg(rFlagsRegU cr, regD src1, regD src2) |
10407 %{ | 10342 %{ |
10456 opcode(0x66, 0x0F, 0x2E); | 10391 opcode(0x66, 0x0F, 0x2E); |
10457 ins_encode(OpcP, REX_reg_mem(src1, src2), OpcS, OpcT, reg_mem(src1, src2)); | 10392 ins_encode(OpcP, REX_reg_mem(src1, src2), OpcS, OpcT, reg_mem(src1, src2)); |
10458 ins_pipe(pipe_slow); | 10393 ins_pipe(pipe_slow); |
10459 %} | 10394 %} |
10460 | 10395 |
10461 instruct cmpD_cc_imm(rFlagsRegU cr, regD src1, immD src2) | 10396 instruct cmpD_cc_imm(rFlagsRegU cr, regD src, immD con) %{ |
10462 %{ | 10397 match(Set cr (CmpD src con)); |
10463 match(Set cr (CmpD src1 src2)); | |
10464 | 10398 |
10465 ins_cost(145); | 10399 ins_cost(145); |
10466 format %{ "ucomisd $src1, [$src2]\n\t" | 10400 format %{ "ucomisd $src, [$constantaddress]\t# load from constant table: double=$con\n\t" |
10467 "jnp,s exit\n\t" | 10401 "jnp,s exit\n\t" |
10468 "pushfq\t# saw NaN, set CF\n\t" | 10402 "pushfq\t# saw NaN, set CF\n\t" |
10469 "andq [rsp], #0xffffff2b\n\t" | 10403 "andq [rsp], #0xffffff2b\n\t" |
10470 "popfq\n" | 10404 "popfq\n" |
10471 "exit: nop\t# avoid branch to branch" %} | 10405 "exit: nop\t# avoid branch to branch" %} |
10472 opcode(0x66, 0x0F, 0x2E); | 10406 ins_encode %{ |
10473 ins_encode(OpcP, REX_reg_mem(src1, src2), OpcS, OpcT, load_immD(src1, src2), | 10407 Label L_exit; |
10474 cmpfp_fixup); | 10408 __ ucomisd($src$$XMMRegister, $constantaddress($con)); |
10409 __ jcc(Assembler::noParity, L_exit); | |
10410 __ pushf(); | |
10411 __ andq(rsp, 0xffffff2b); | |
10412 __ popf(); | |
10413 __ bind(L_exit); | |
10414 __ nop(); | |
10415 %} | |
10475 ins_pipe(pipe_slow); | 10416 ins_pipe(pipe_slow); |
10476 %} | 10417 %} |
10477 | 10418 |
10478 instruct cmpD_cc_immCF(rFlagsRegUCF cr, regD src1, immD src2) %{ | 10419 instruct cmpD_cc_immCF(rFlagsRegUCF cr, regD src, immD con) %{ |
10479 match(Set cr (CmpD src1 src2)); | 10420 match(Set cr (CmpD src con)); |
10480 | |
10481 ins_cost(100); | 10421 ins_cost(100); |
10482 format %{ "ucomisd $src1, [$src2]" %} | 10422 format %{ "ucomisd $src, [$constantaddress]\t# load from constant table: double=$con" %} |
10483 opcode(0x66, 0x0F, 0x2E); | 10423 ins_encode %{ |
10484 ins_encode(OpcP, REX_reg_mem(src1, src2), OpcS, OpcT, load_immD(src1, src2)); | 10424 __ ucomisd($src$$XMMRegister, $constantaddress($con)); |
10425 %} | |
10485 ins_pipe(pipe_slow); | 10426 ins_pipe(pipe_slow); |
10486 %} | 10427 %} |
10487 | 10428 |
10488 // Compare into -1,0,1 | 10429 // Compare into -1,0,1 |
10489 instruct cmpF_reg(rRegI dst, regF src1, regF src2, rFlagsReg cr) | 10430 instruct cmpF_reg(rRegI dst, regF src1, regF src2, rFlagsReg cr) |
10526 cmpfp3(dst)); | 10467 cmpfp3(dst)); |
10527 ins_pipe(pipe_slow); | 10468 ins_pipe(pipe_slow); |
10528 %} | 10469 %} |
10529 | 10470 |
10530 // Compare into -1,0,1 | 10471 // Compare into -1,0,1 |
10531 instruct cmpF_imm(rRegI dst, regF src1, immF src2, rFlagsReg cr) | 10472 instruct cmpF_imm(rRegI dst, regF src, immF con, rFlagsReg cr) %{ |
10532 %{ | 10473 match(Set dst (CmpF3 src con)); |
10533 match(Set dst (CmpF3 src1 src2)); | |
10534 effect(KILL cr); | 10474 effect(KILL cr); |
10535 | 10475 |
10536 ins_cost(275); | 10476 ins_cost(275); |
10537 format %{ "ucomiss $src1, [$src2]\n\t" | 10477 format %{ "ucomiss $src, [$constantaddress]\t# load from constant table: float=$con\n\t" |
10538 "movl $dst, #-1\n\t" | 10478 "movl $dst, #-1\n\t" |
10539 "jp,s done\n\t" | 10479 "jp,s done\n\t" |
10540 "jb,s done\n\t" | 10480 "jb,s done\n\t" |
10541 "setne $dst\n\t" | 10481 "setne $dst\n\t" |
10542 "movzbl $dst, $dst\n" | 10482 "movzbl $dst, $dst\n" |
10543 "done:" %} | 10483 "done:" %} |
10544 | 10484 ins_encode %{ |
10545 opcode(0x0F, 0x2E); | 10485 Label L_done; |
10546 ins_encode(REX_reg_mem(src1, src2), OpcP, OpcS, load_immF(src1, src2), | 10486 Register Rdst = $dst$$Register; |
10547 cmpfp3(dst)); | 10487 __ ucomiss($src$$XMMRegister, $constantaddress($con)); |
10488 __ movl(Rdst, -1); | |
10489 __ jcc(Assembler::parity, L_done); | |
10490 __ jcc(Assembler::below, L_done); | |
10491 __ setb(Assembler::notEqual, Rdst); | |
10492 __ movzbl(Rdst, Rdst); | |
10493 __ bind(L_done); | |
10494 %} | |
10548 ins_pipe(pipe_slow); | 10495 ins_pipe(pipe_slow); |
10549 %} | 10496 %} |
10550 | 10497 |
10551 // Compare into -1,0,1 | 10498 // Compare into -1,0,1 |
10552 instruct cmpD_reg(rRegI dst, regD src1, regD src2, rFlagsReg cr) | 10499 instruct cmpD_reg(rRegI dst, regD src1, regD src2, rFlagsReg cr) |
10589 cmpfp3(dst)); | 10536 cmpfp3(dst)); |
10590 ins_pipe(pipe_slow); | 10537 ins_pipe(pipe_slow); |
10591 %} | 10538 %} |
10592 | 10539 |
10593 // Compare into -1,0,1 | 10540 // Compare into -1,0,1 |
10594 instruct cmpD_imm(rRegI dst, regD src1, immD src2, rFlagsReg cr) | 10541 instruct cmpD_imm(rRegI dst, regD src, immD con, rFlagsReg cr) %{ |
10595 %{ | 10542 match(Set dst (CmpD3 src con)); |
10596 match(Set dst (CmpD3 src1 src2)); | |
10597 effect(KILL cr); | 10543 effect(KILL cr); |
10598 | 10544 |
10599 ins_cost(275); | 10545 ins_cost(275); |
10600 format %{ "ucomisd $src1, [$src2]\n\t" | 10546 format %{ "ucomisd $src, [$constantaddress]\t# load from constant table: double=$con\n\t" |
10601 "movl $dst, #-1\n\t" | 10547 "movl $dst, #-1\n\t" |
10602 "jp,s done\n\t" | 10548 "jp,s done\n\t" |
10603 "jb,s done\n\t" | 10549 "jb,s done\n\t" |
10604 "setne $dst\n\t" | 10550 "setne $dst\n\t" |
10605 "movzbl $dst, $dst\n" | 10551 "movzbl $dst, $dst\n" |
10606 "done:" %} | 10552 "done:" %} |
10607 | 10553 ins_encode %{ |
10608 opcode(0x66, 0x0F, 0x2E); | 10554 Register Rdst = $dst$$Register; |
10609 ins_encode(OpcP, REX_reg_mem(src1, src2), OpcS, OpcT, load_immD(src1, src2), | 10555 Label L_done; |
10610 cmpfp3(dst)); | 10556 __ ucomisd($src$$XMMRegister, $constantaddress($con)); |
10557 __ movl(Rdst, -1); | |
10558 __ jcc(Assembler::parity, L_done); | |
10559 __ jcc(Assembler::below, L_done); | |
10560 __ setb(Assembler::notEqual, Rdst); | |
10561 __ movzbl(Rdst, Rdst); | |
10562 __ bind(L_done); | |
10563 %} | |
10611 ins_pipe(pipe_slow); | 10564 ins_pipe(pipe_slow); |
10612 %} | 10565 %} |
10613 | 10566 |
10614 instruct addF_reg(regF dst, regF src) | 10567 instruct addF_reg(regF dst, regF src) |
10615 %{ | 10568 %{ |
10631 opcode(0xF3, 0x0F, 0x58); | 10584 opcode(0xF3, 0x0F, 0x58); |
10632 ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, reg_mem(dst, src)); | 10585 ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, reg_mem(dst, src)); |
10633 ins_pipe(pipe_slow); | 10586 ins_pipe(pipe_slow); |
10634 %} | 10587 %} |
10635 | 10588 |
10636 instruct addF_imm(regF dst, immF src) | 10589 instruct addF_imm(regF dst, immF con) %{ |
10637 %{ | 10590 match(Set dst (AddF dst con)); |
10638 match(Set dst (AddF dst src)); | 10591 format %{ "addss $dst, [$constantaddress]\t# load from constant table: float=$con" %} |
10639 | |
10640 format %{ "addss $dst, [$src]" %} | |
10641 ins_cost(150); // XXX | 10592 ins_cost(150); // XXX |
10642 opcode(0xF3, 0x0F, 0x58); | 10593 ins_encode %{ |
10643 ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immF(dst, src)); | 10594 __ addss($dst$$XMMRegister, $constantaddress($con)); |
10595 %} | |
10644 ins_pipe(pipe_slow); | 10596 ins_pipe(pipe_slow); |
10645 %} | 10597 %} |
10646 | 10598 |
10647 instruct addD_reg(regD dst, regD src) | 10599 instruct addD_reg(regD dst, regD src) |
10648 %{ | 10600 %{ |
10664 opcode(0xF2, 0x0F, 0x58); | 10616 opcode(0xF2, 0x0F, 0x58); |
10665 ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, reg_mem(dst, src)); | 10617 ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, reg_mem(dst, src)); |
10666 ins_pipe(pipe_slow); | 10618 ins_pipe(pipe_slow); |
10667 %} | 10619 %} |
10668 | 10620 |
10669 instruct addD_imm(regD dst, immD src) | 10621 instruct addD_imm(regD dst, immD con) %{ |
10670 %{ | 10622 match(Set dst (AddD dst con)); |
10671 match(Set dst (AddD dst src)); | 10623 format %{ "addsd $dst, [$constantaddress]\t# load from constant table: double=$con" %} |
10672 | |
10673 format %{ "addsd $dst, [$src]" %} | |
10674 ins_cost(150); // XXX | 10624 ins_cost(150); // XXX |
10675 opcode(0xF2, 0x0F, 0x58); | 10625 ins_encode %{ |
10676 ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immD(dst, src)); | 10626 __ addsd($dst$$XMMRegister, $constantaddress($con)); |
10627 %} | |
10677 ins_pipe(pipe_slow); | 10628 ins_pipe(pipe_slow); |
10678 %} | 10629 %} |
10679 | 10630 |
10680 instruct subF_reg(regF dst, regF src) | 10631 instruct subF_reg(regF dst, regF src) |
10681 %{ | 10632 %{ |
10697 opcode(0xF3, 0x0F, 0x5C); | 10648 opcode(0xF3, 0x0F, 0x5C); |
10698 ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, reg_mem(dst, src)); | 10649 ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, reg_mem(dst, src)); |
10699 ins_pipe(pipe_slow); | 10650 ins_pipe(pipe_slow); |
10700 %} | 10651 %} |
10701 | 10652 |
10702 instruct subF_imm(regF dst, immF src) | 10653 instruct subF_imm(regF dst, immF con) %{ |
10703 %{ | 10654 match(Set dst (SubF dst con)); |
10704 match(Set dst (SubF dst src)); | 10655 format %{ "subss $dst, [$constantaddress]\t# load from constant table: float=$con" %} |
10705 | |
10706 format %{ "subss $dst, [$src]" %} | |
10707 ins_cost(150); // XXX | 10656 ins_cost(150); // XXX |
10708 opcode(0xF3, 0x0F, 0x5C); | 10657 ins_encode %{ |
10709 ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immF(dst, src)); | 10658 __ subss($dst$$XMMRegister, $constantaddress($con)); |
10659 %} | |
10710 ins_pipe(pipe_slow); | 10660 ins_pipe(pipe_slow); |
10711 %} | 10661 %} |
10712 | 10662 |
10713 instruct subD_reg(regD dst, regD src) | 10663 instruct subD_reg(regD dst, regD src) |
10714 %{ | 10664 %{ |
10730 opcode(0xF2, 0x0F, 0x5C); | 10680 opcode(0xF2, 0x0F, 0x5C); |
10731 ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, reg_mem(dst, src)); | 10681 ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, reg_mem(dst, src)); |
10732 ins_pipe(pipe_slow); | 10682 ins_pipe(pipe_slow); |
10733 %} | 10683 %} |
10734 | 10684 |
10735 instruct subD_imm(regD dst, immD src) | 10685 instruct subD_imm(regD dst, immD con) %{ |
10736 %{ | 10686 match(Set dst (SubD dst con)); |
10737 match(Set dst (SubD dst src)); | 10687 format %{ "subsd $dst, [$constantaddress]\t# load from constant table: double=$con" %} |
10738 | |
10739 format %{ "subsd $dst, [$src]" %} | |
10740 ins_cost(150); // XXX | 10688 ins_cost(150); // XXX |
10741 opcode(0xF2, 0x0F, 0x5C); | 10689 ins_encode %{ |
10742 ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immD(dst, src)); | 10690 __ subsd($dst$$XMMRegister, $constantaddress($con)); |
10691 %} | |
10743 ins_pipe(pipe_slow); | 10692 ins_pipe(pipe_slow); |
10744 %} | 10693 %} |
10745 | 10694 |
10746 instruct mulF_reg(regF dst, regF src) | 10695 instruct mulF_reg(regF dst, regF src) |
10747 %{ | 10696 %{ |
10763 opcode(0xF3, 0x0F, 0x59); | 10712 opcode(0xF3, 0x0F, 0x59); |
10764 ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, reg_mem(dst, src)); | 10713 ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, reg_mem(dst, src)); |
10765 ins_pipe(pipe_slow); | 10714 ins_pipe(pipe_slow); |
10766 %} | 10715 %} |
10767 | 10716 |
10768 instruct mulF_imm(regF dst, immF src) | 10717 instruct mulF_imm(regF dst, immF con) %{ |
10769 %{ | 10718 match(Set dst (MulF dst con)); |
10770 match(Set dst (MulF dst src)); | 10719 format %{ "mulss $dst, [$constantaddress]\t# load from constant table: float=$con" %} |
10771 | |
10772 format %{ "mulss $dst, [$src]" %} | |
10773 ins_cost(150); // XXX | 10720 ins_cost(150); // XXX |
10774 opcode(0xF3, 0x0F, 0x59); | 10721 ins_encode %{ |
10775 ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immF(dst, src)); | 10722 __ mulss($dst$$XMMRegister, $constantaddress($con)); |
10723 %} | |
10776 ins_pipe(pipe_slow); | 10724 ins_pipe(pipe_slow); |
10777 %} | 10725 %} |
10778 | 10726 |
10779 instruct mulD_reg(regD dst, regD src) | 10727 instruct mulD_reg(regD dst, regD src) |
10780 %{ | 10728 %{ |
10796 opcode(0xF2, 0x0F, 0x59); | 10744 opcode(0xF2, 0x0F, 0x59); |
10797 ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, reg_mem(dst, src)); | 10745 ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, reg_mem(dst, src)); |
10798 ins_pipe(pipe_slow); | 10746 ins_pipe(pipe_slow); |
10799 %} | 10747 %} |
10800 | 10748 |
10801 instruct mulD_imm(regD dst, immD src) | 10749 instruct mulD_imm(regD dst, immD con) %{ |
10802 %{ | 10750 match(Set dst (MulD dst con)); |
10803 match(Set dst (MulD dst src)); | 10751 format %{ "mulsd $dst, [$constantaddress]\t# load from constant table: double=$con" %} |
10804 | |
10805 format %{ "mulsd $dst, [$src]" %} | |
10806 ins_cost(150); // XXX | 10752 ins_cost(150); // XXX |
10807 opcode(0xF2, 0x0F, 0x59); | 10753 ins_encode %{ |
10808 ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immD(dst, src)); | 10754 __ mulsd($dst$$XMMRegister, $constantaddress($con)); |
10755 %} | |
10809 ins_pipe(pipe_slow); | 10756 ins_pipe(pipe_slow); |
10810 %} | 10757 %} |
10811 | 10758 |
10812 instruct divF_reg(regF dst, regF src) | 10759 instruct divF_reg(regF dst, regF src) |
10813 %{ | 10760 %{ |
10829 opcode(0xF3, 0x0F, 0x5E); | 10776 opcode(0xF3, 0x0F, 0x5E); |
10830 ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, reg_mem(dst, src)); | 10777 ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, reg_mem(dst, src)); |
10831 ins_pipe(pipe_slow); | 10778 ins_pipe(pipe_slow); |
10832 %} | 10779 %} |
10833 | 10780 |
10834 instruct divF_imm(regF dst, immF src) | 10781 instruct divF_imm(regF dst, immF con) %{ |
10835 %{ | 10782 match(Set dst (DivF dst con)); |
10836 match(Set dst (DivF dst src)); | 10783 format %{ "divss $dst, [$constantaddress]\t# load from constant table: float=$con" %} |
10837 | |
10838 format %{ "divss $dst, [$src]" %} | |
10839 ins_cost(150); // XXX | 10784 ins_cost(150); // XXX |
10840 opcode(0xF3, 0x0F, 0x5E); | 10785 ins_encode %{ |
10841 ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immF(dst, src)); | 10786 __ divss($dst$$XMMRegister, $constantaddress($con)); |
10787 %} | |
10842 ins_pipe(pipe_slow); | 10788 ins_pipe(pipe_slow); |
10843 %} | 10789 %} |
10844 | 10790 |
10845 instruct divD_reg(regD dst, regD src) | 10791 instruct divD_reg(regD dst, regD src) |
10846 %{ | 10792 %{ |
10862 opcode(0xF2, 0x0F, 0x5E); | 10808 opcode(0xF2, 0x0F, 0x5E); |
10863 ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, reg_mem(dst, src)); | 10809 ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, reg_mem(dst, src)); |
10864 ins_pipe(pipe_slow); | 10810 ins_pipe(pipe_slow); |
10865 %} | 10811 %} |
10866 | 10812 |
10867 instruct divD_imm(regD dst, immD src) | 10813 instruct divD_imm(regD dst, immD con) %{ |
10868 %{ | 10814 match(Set dst (DivD dst con)); |
10869 match(Set dst (DivD dst src)); | 10815 format %{ "divsd $dst, [$constantaddress]\t# load from constant table: double=$con" %} |
10870 | |
10871 format %{ "divsd $dst, [$src]" %} | |
10872 ins_cost(150); // XXX | 10816 ins_cost(150); // XXX |
10873 opcode(0xF2, 0x0F, 0x5E); | 10817 ins_encode %{ |
10874 ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immD(dst, src)); | 10818 __ divsd($dst$$XMMRegister, $constantaddress($con)); |
10819 %} | |
10875 ins_pipe(pipe_slow); | 10820 ins_pipe(pipe_slow); |
10876 %} | 10821 %} |
10877 | 10822 |
10878 instruct sqrtF_reg(regF dst, regF src) | 10823 instruct sqrtF_reg(regF dst, regF src) |
10879 %{ | 10824 %{ |
10895 opcode(0xF3, 0x0F, 0x51); | 10840 opcode(0xF3, 0x0F, 0x51); |
10896 ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, reg_mem(dst, src)); | 10841 ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, reg_mem(dst, src)); |
10897 ins_pipe(pipe_slow); | 10842 ins_pipe(pipe_slow); |
10898 %} | 10843 %} |
10899 | 10844 |
10900 instruct sqrtF_imm(regF dst, immF src) | 10845 instruct sqrtF_imm(regF dst, immF con) %{ |
10901 %{ | 10846 match(Set dst (ConvD2F (SqrtD (ConvF2D con)))); |
10902 match(Set dst (ConvD2F (SqrtD (ConvF2D src)))); | 10847 format %{ "sqrtss $dst, [$constantaddress]\t# load from constant table: float=$con" %} |
10903 | |
10904 format %{ "sqrtss $dst, [$src]" %} | |
10905 ins_cost(150); // XXX | 10848 ins_cost(150); // XXX |
10906 opcode(0xF3, 0x0F, 0x51); | 10849 ins_encode %{ |
10907 ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immF(dst, src)); | 10850 __ sqrtss($dst$$XMMRegister, $constantaddress($con)); |
10851 %} | |
10908 ins_pipe(pipe_slow); | 10852 ins_pipe(pipe_slow); |
10909 %} | 10853 %} |
10910 | 10854 |
10911 instruct sqrtD_reg(regD dst, regD src) | 10855 instruct sqrtD_reg(regD dst, regD src) |
10912 %{ | 10856 %{ |
10928 opcode(0xF2, 0x0F, 0x51); | 10872 opcode(0xF2, 0x0F, 0x51); |
10929 ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, reg_mem(dst, src)); | 10873 ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, reg_mem(dst, src)); |
10930 ins_pipe(pipe_slow); | 10874 ins_pipe(pipe_slow); |
10931 %} | 10875 %} |
10932 | 10876 |
10933 instruct sqrtD_imm(regD dst, immD src) | 10877 instruct sqrtD_imm(regD dst, immD con) %{ |
10934 %{ | 10878 match(Set dst (SqrtD con)); |
10935 match(Set dst (SqrtD src)); | 10879 format %{ "sqrtsd $dst, [$constantaddress]\t# load from constant table: double=$con" %} |
10936 | |
10937 format %{ "sqrtsd $dst, [$src]" %} | |
10938 ins_cost(150); // XXX | 10880 ins_cost(150); // XXX |
10939 opcode(0xF2, 0x0F, 0x51); | 10881 ins_encode %{ |
10940 ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immD(dst, src)); | 10882 __ sqrtsd($dst$$XMMRegister, $constantaddress($con)); |
10883 %} | |
10941 ins_pipe(pipe_slow); | 10884 ins_pipe(pipe_slow); |
10942 %} | 10885 %} |
10943 | 10886 |
10944 instruct absF_reg(regF dst) | 10887 instruct absF_reg(regF dst) |
10945 %{ | 10888 %{ |