Mercurial > hg > truffle
comparison src/cpu/x86/vm/x86_64.ad @ 344:6aae2f9d0294
Merge
author | ysr |
---|---|
date | Thu, 12 Jun 2008 13:50:55 -0700 |
parents | 44abbb0d4c18 |
children | d1605aabd0a1 1e026f8da827 |
comparison
equal
deleted
inserted
replaced
342:37f87013dfd8 | 344:6aae2f9d0294 |
---|---|
3806 | 3806 |
3807 // That's it | 3807 // That's it |
3808 masm.bind(DONE_LABEL); | 3808 masm.bind(DONE_LABEL); |
3809 %} | 3809 %} |
3810 | 3810 |
3811 enc_class enc_Array_Equals(rdi_RegP ary1, rsi_RegP ary2, rax_RegI tmp1, rbx_RegI tmp2, rcx_RegI result) %{ | |
3812 Label TRUE_LABEL, FALSE_LABEL, DONE_LABEL, COMPARE_LOOP_HDR, COMPARE_LOOP; | |
3813 MacroAssembler masm(&cbuf); | |
3814 | |
3815 Register ary1Reg = as_Register($ary1$$reg); | |
3816 Register ary2Reg = as_Register($ary2$$reg); | |
3817 Register tmp1Reg = as_Register($tmp1$$reg); | |
3818 Register tmp2Reg = as_Register($tmp2$$reg); | |
3819 Register resultReg = as_Register($result$$reg); | |
3820 | |
3821 int length_offset = arrayOopDesc::length_offset_in_bytes(); | |
3822 int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); | |
3823 | |
3824 // Check the input args | |
3825 masm.cmpq(ary1Reg, ary2Reg); | |
3826 masm.jcc(Assembler::equal, TRUE_LABEL); | |
3827 masm.testq(ary1Reg, ary1Reg); | |
3828 masm.jcc(Assembler::zero, FALSE_LABEL); | |
3829 masm.testq(ary2Reg, ary2Reg); | |
3830 masm.jcc(Assembler::zero, FALSE_LABEL); | |
3831 | |
3832 // Check the lengths | |
3833 masm.movl(tmp2Reg, Address(ary1Reg, length_offset)); | |
3834 masm.movl(resultReg, Address(ary2Reg, length_offset)); | |
3835 masm.cmpl(tmp2Reg, resultReg); | |
3836 masm.jcc(Assembler::notEqual, FALSE_LABEL); | |
3837 masm.testl(resultReg, resultReg); | |
3838 masm.jcc(Assembler::zero, TRUE_LABEL); | |
3839 | |
3840 // Get the number of 4 byte vectors to compare | |
3841 masm.shrl(resultReg, 1); | |
3842 | |
3843 // Check for odd-length arrays | |
3844 masm.andl(tmp2Reg, 1); | |
3845 masm.testl(tmp2Reg, tmp2Reg); | |
3846 masm.jcc(Assembler::zero, COMPARE_LOOP_HDR); | |
3847 | |
3848 // Compare 2-byte "tail" at end of arrays | |
3849 masm.load_unsigned_word(tmp1Reg, Address(ary1Reg, resultReg, Address::times_4, base_offset)); | |
3850 masm.load_unsigned_word(tmp2Reg, Address(ary2Reg, resultReg, Address::times_4, base_offset)); | |
3851 masm.cmpl(tmp1Reg, tmp2Reg); | |
3852 masm.jcc(Assembler::notEqual, FALSE_LABEL); | |
3853 masm.testl(resultReg, resultReg); | |
3854 masm.jcc(Assembler::zero, TRUE_LABEL); | |
3855 | |
3856 // Setup compare loop | |
3857 masm.bind(COMPARE_LOOP_HDR); | |
3858 // Shift tmp1Reg and tmp2Reg to the last 4-byte boundary of the arrays | |
3859 masm.leaq(tmp1Reg, Address(ary1Reg, resultReg, Address::times_4, base_offset)); | |
3860 masm.leaq(tmp2Reg, Address(ary2Reg, resultReg, Address::times_4, base_offset)); | |
3861 masm.negq(resultReg); | |
3862 | |
3863 // 4-byte-wide compare loop | |
3864 masm.bind(COMPARE_LOOP); | |
3865 masm.movl(ary1Reg, Address(tmp1Reg, resultReg, Address::times_4, 0)); | |
3866 masm.movl(ary2Reg, Address(tmp2Reg, resultReg, Address::times_4, 0)); | |
3867 masm.cmpl(ary1Reg, ary2Reg); | |
3868 masm.jcc(Assembler::notEqual, FALSE_LABEL); | |
3869 masm.incrementq(resultReg); | |
3870 masm.jcc(Assembler::notZero, COMPARE_LOOP); | |
3871 | |
3872 masm.bind(TRUE_LABEL); | |
3873 masm.movl(resultReg, 1); // return true | |
3874 masm.jmp(DONE_LABEL); | |
3875 | |
3876 masm.bind(FALSE_LABEL); | |
3877 masm.xorl(resultReg, resultReg); // return false | |
3878 | |
3879 // That's it | |
3880 masm.bind(DONE_LABEL); | |
3881 %} | |
3882 | |
3811 enc_class enc_rethrow() | 3883 enc_class enc_rethrow() |
3812 %{ | 3884 %{ |
3813 cbuf.set_inst_mark(); | 3885 cbuf.set_inst_mark(); |
3814 emit_opcode(cbuf, 0xE9); // jmp entry | 3886 emit_opcode(cbuf, 0xE9); // jmp entry |
3815 emit_d32_reloc(cbuf, | 3887 emit_d32_reloc(cbuf, |
5200 scale($scale); | 5272 scale($scale); |
5201 disp($off); | 5273 disp($off); |
5202 %} | 5274 %} |
5203 %} | 5275 %} |
5204 | 5276 |
5205 // Indirect Memory Times Scale Plus Index Register Plus Offset Operand | 5277 // Indirect Narrow Oop Plus Offset Operand |
5206 operand indIndexScaleOffsetComp(rRegN src, immL32 off, r12RegL base) %{ | 5278 operand indNarrowOopOffset(rRegN src, immL32 off) %{ |
5207 constraint(ALLOC_IN_RC(ptr_reg)); | 5279 constraint(ALLOC_IN_RC(ptr_reg)); |
5208 match(AddP (DecodeN src base) off); | 5280 match(AddP (DecodeN src) off); |
5209 | 5281 |
5210 op_cost(10); | 5282 op_cost(10); |
5211 format %{"[$base + $src << 3 + $off] (compressed)" %} | 5283 format %{"[R12 + $src << 3 + $off] (compressed oop addressing)" %} |
5212 interface(MEMORY_INTER) %{ | 5284 interface(MEMORY_INTER) %{ |
5213 base($base); | 5285 base(0xc); // R12 |
5214 index($src); | 5286 index($src); |
5215 scale(0x3); | 5287 scale(0x3); |
5216 disp($off); | 5288 disp($off); |
5217 %} | 5289 %} |
5218 %} | 5290 %} |
5363 // multiple operand types with the same basic encoding and format. The classic | 5435 // multiple operand types with the same basic encoding and format. The classic |
5364 // case of this is memory operands. | 5436 // case of this is memory operands. |
5365 | 5437 |
5366 opclass memory(indirect, indOffset8, indOffset32, indIndexOffset, indIndex, | 5438 opclass memory(indirect, indOffset8, indOffset32, indIndexOffset, indIndex, |
5367 indIndexScale, indIndexScaleOffset, indPosIndexScaleOffset, | 5439 indIndexScale, indIndexScaleOffset, indPosIndexScaleOffset, |
5368 indIndexScaleOffsetComp); | 5440 indNarrowOopOffset); |
5369 | 5441 |
5370 //----------PIPELINE----------------------------------------------------------- | 5442 //----------PIPELINE----------------------------------------------------------- |
5371 // Rules which define the behavior of the target architectures pipeline. | 5443 // Rules which define the behavior of the target architectures pipeline. |
5372 pipeline %{ | 5444 pipeline %{ |
5373 | 5445 |
6042 ins_encode(REX_reg_mem_wide(dst, mem), OpcP, reg_mem(dst, mem)); | 6114 ins_encode(REX_reg_mem_wide(dst, mem), OpcP, reg_mem(dst, mem)); |
6043 ins_pipe(ialu_reg_mem); // XXX | 6115 ins_pipe(ialu_reg_mem); // XXX |
6044 %} | 6116 %} |
6045 | 6117 |
6046 // Load Compressed Pointer | 6118 // Load Compressed Pointer |
6047 instruct loadN(rRegN dst, memory mem, rFlagsReg cr) | 6119 instruct loadN(rRegN dst, memory mem) |
6048 %{ | 6120 %{ |
6049 match(Set dst (LoadN mem)); | 6121 match(Set dst (LoadN mem)); |
6050 effect(KILL cr); | |
6051 | 6122 |
6052 ins_cost(125); // XXX | 6123 ins_cost(125); // XXX |
6053 format %{ "movl $dst, $mem\t# compressed ptr" %} | 6124 format %{ "movl $dst, $mem\t# compressed ptr" %} |
6054 ins_encode %{ | 6125 ins_encode %{ |
6055 Address addr = build_address($mem$$base, $mem$$index, $mem$$scale, $mem$$disp); | 6126 Address addr = build_address($mem$$base, $mem$$index, $mem$$scale, $mem$$disp); |
6062 | 6133 |
6063 // Load Klass Pointer | 6134 // Load Klass Pointer |
6064 instruct loadKlass(rRegP dst, memory mem) | 6135 instruct loadKlass(rRegP dst, memory mem) |
6065 %{ | 6136 %{ |
6066 match(Set dst (LoadKlass mem)); | 6137 match(Set dst (LoadKlass mem)); |
6067 predicate(!n->in(MemNode::Address)->bottom_type()->is_narrow()); | |
6068 | 6138 |
6069 ins_cost(125); // XXX | 6139 ins_cost(125); // XXX |
6070 format %{ "movq $dst, $mem\t# class" %} | 6140 format %{ "movq $dst, $mem\t# class" %} |
6071 opcode(0x8B); | 6141 opcode(0x8B); |
6072 ins_encode(REX_reg_mem_wide(dst, mem), OpcP, reg_mem(dst, mem)); | 6142 ins_encode(REX_reg_mem_wide(dst, mem), OpcP, reg_mem(dst, mem)); |
6073 ins_pipe(ialu_reg_mem); // XXX | 6143 ins_pipe(ialu_reg_mem); // XXX |
6074 %} | 6144 %} |
6075 | 6145 |
6076 // Load Klass Pointer | 6146 // Load narrow Klass Pointer |
6077 instruct loadKlassComp(rRegP dst, memory mem) | 6147 instruct loadNKlass(rRegN dst, memory mem) |
6078 %{ | 6148 %{ |
6079 match(Set dst (LoadKlass mem)); | 6149 match(Set dst (LoadNKlass mem)); |
6080 predicate(n->in(MemNode::Address)->bottom_type()->is_narrow()); | |
6081 | 6150 |
6082 ins_cost(125); // XXX | 6151 ins_cost(125); // XXX |
6083 format %{ "movl $dst, $mem\t# compressed class\n\t" | 6152 format %{ "movl $dst, $mem\t# compressed klass ptr" %} |
6084 "decode_heap_oop $dst,$dst" %} | |
6085 ins_encode %{ | 6153 ins_encode %{ |
6086 Address addr = build_address($mem$$base, $mem$$index, $mem$$scale, $mem$$disp); | 6154 Address addr = build_address($mem$$base, $mem$$index, $mem$$scale, $mem$$disp); |
6087 Register dst = as_Register($dst$$reg); | 6155 Register dst = as_Register($dst$$reg); |
6088 __ movl(dst, addr); | 6156 __ movl(dst, addr); |
6089 // klass is never null in the header but this is generated for all | |
6090 // klass loads not just the _klass field in the header. | |
6091 __ decode_heap_oop(dst); | |
6092 %} | 6157 %} |
6093 ins_pipe(ialu_reg_mem); // XXX | 6158 ins_pipe(ialu_reg_mem); // XXX |
6094 %} | 6159 %} |
6095 | 6160 |
6096 // Load Float | 6161 // Load Float |
6360 | 6425 |
6361 instruct loadConN(rRegN dst, immN src) %{ | 6426 instruct loadConN(rRegN dst, immN src) %{ |
6362 match(Set dst src); | 6427 match(Set dst src); |
6363 | 6428 |
6364 ins_cost(125); | 6429 ins_cost(125); |
6365 format %{ "movq $dst, $src\t# compressed ptr\n\t" | 6430 format %{ "movl $dst, $src\t# compressed ptr" %} |
6366 "encode_heap_oop_not_null $dst,$dst" %} | |
6367 ins_encode %{ | 6431 ins_encode %{ |
6368 address con = (address)$src$$constant; | 6432 address con = (address)$src$$constant; |
6369 Register dst = $dst$$Register; | 6433 Register dst = $dst$$Register; |
6370 if (con == NULL) { | 6434 if (con == NULL) { |
6371 ShouldNotReachHere(); | 6435 ShouldNotReachHere(); |
6372 } else { | 6436 } else { |
6373 __ movoop(dst, (jobject)$src$$constant); | 6437 __ set_narrow_oop(dst, (jobject)$src$$constant); |
6374 __ encode_heap_oop_not_null(dst); | |
6375 } | 6438 } |
6376 %} | 6439 %} |
6377 ins_pipe(ialu_reg_fat); // XXX | 6440 ins_pipe(ialu_reg_fat); // XXX |
6378 %} | 6441 %} |
6379 | 6442 |
6631 ins_encode(REX_mem_wide(mem), OpcP, RM_opc_mem(0x00, mem), Con32(src)); | 6694 ins_encode(REX_mem_wide(mem), OpcP, RM_opc_mem(0x00, mem), Con32(src)); |
6632 ins_pipe(ialu_mem_imm); | 6695 ins_pipe(ialu_mem_imm); |
6633 %} | 6696 %} |
6634 | 6697 |
6635 // Store Compressed Pointer | 6698 // Store Compressed Pointer |
6636 instruct storeN(memory mem, rRegN src, rFlagsReg cr) | 6699 instruct storeN(memory mem, rRegN src) |
6637 %{ | 6700 %{ |
6638 match(Set mem (StoreN mem src)); | 6701 match(Set mem (StoreN mem src)); |
6639 effect(KILL cr); | |
6640 | 6702 |
6641 ins_cost(125); // XXX | 6703 ins_cost(125); // XXX |
6642 format %{ "movl $mem, $src\t# ptr" %} | 6704 format %{ "movl $mem, $src\t# compressed ptr" %} |
6643 ins_encode %{ | 6705 ins_encode %{ |
6644 Address addr = build_address($mem$$base, $mem$$index, $mem$$scale, $mem$$disp); | 6706 Address addr = build_address($mem$$base, $mem$$index, $mem$$scale, $mem$$disp); |
6645 Register src = as_Register($src$$reg); | 6707 Register src = as_Register($src$$reg); |
6646 __ movl(addr, src); | 6708 __ movl(addr, src); |
6647 %} | 6709 %} |
7025 %} | 7087 %} |
7026 ins_pipe(ialu_reg_long); | 7088 ins_pipe(ialu_reg_long); |
7027 %} | 7089 %} |
7028 | 7090 |
7029 instruct decodeHeapOop(rRegP dst, rRegN src, rFlagsReg cr) %{ | 7091 instruct decodeHeapOop(rRegP dst, rRegN src, rFlagsReg cr) %{ |
7030 predicate(n->bottom_type()->is_oopptr()->ptr() != TypePtr::NotNull); | 7092 predicate(n->bottom_type()->is_oopptr()->ptr() != TypePtr::NotNull && |
7093 n->bottom_type()->is_oopptr()->ptr() != TypePtr::Constant); | |
7031 match(Set dst (DecodeN src)); | 7094 match(Set dst (DecodeN src)); |
7032 effect(KILL cr); | 7095 effect(KILL cr); |
7033 format %{ "decode_heap_oop $dst,$src" %} | 7096 format %{ "decode_heap_oop $dst,$src" %} |
7034 ins_encode %{ | 7097 ins_encode %{ |
7035 Register s = $src$$Register; | 7098 Register s = $src$$Register; |
7041 %} | 7104 %} |
7042 ins_pipe(ialu_reg_long); | 7105 ins_pipe(ialu_reg_long); |
7043 %} | 7106 %} |
7044 | 7107 |
7045 instruct decodeHeapOop_not_null(rRegP dst, rRegN src) %{ | 7108 instruct decodeHeapOop_not_null(rRegP dst, rRegN src) %{ |
7046 predicate(n->bottom_type()->is_oopptr()->ptr() == TypePtr::NotNull); | 7109 predicate(n->bottom_type()->is_oopptr()->ptr() == TypePtr::NotNull || |
7110 n->bottom_type()->is_oopptr()->ptr() == TypePtr::Constant); | |
7047 match(Set dst (DecodeN src)); | 7111 match(Set dst (DecodeN src)); |
7048 format %{ "decode_heap_oop_not_null $dst,$src" %} | 7112 format %{ "decode_heap_oop_not_null $dst,$src" %} |
7049 ins_encode %{ | 7113 ins_encode %{ |
7050 Register s = $src$$Register; | 7114 Register s = $src$$Register; |
7051 Register d = $dst$$Register; | 7115 Register d = $dst$$Register; |
7138 ins_cost(250); // XXX | 7202 ins_cost(250); // XXX |
7139 format %{ "cmovl$cop $dst, $src\t# unsigned, int" %} | 7203 format %{ "cmovl$cop $dst, $src\t# unsigned, int" %} |
7140 opcode(0x0F, 0x40); | 7204 opcode(0x0F, 0x40); |
7141 ins_encode(REX_reg_mem(dst, src), enc_cmov(cop), reg_mem(dst, src)); | 7205 ins_encode(REX_reg_mem(dst, src), enc_cmov(cop), reg_mem(dst, src)); |
7142 ins_pipe(pipe_cmov_mem); | 7206 ins_pipe(pipe_cmov_mem); |
7207 %} | |
7208 | |
7209 // Conditional move | |
7210 instruct cmovN_reg(rRegN dst, rRegN src, rFlagsReg cr, cmpOp cop) | |
7211 %{ | |
7212 match(Set dst (CMoveN (Binary cop cr) (Binary dst src))); | |
7213 | |
7214 ins_cost(200); // XXX | |
7215 format %{ "cmovl$cop $dst, $src\t# signed, compressed ptr" %} | |
7216 opcode(0x0F, 0x40); | |
7217 ins_encode(REX_reg_reg(dst, src), enc_cmov(cop), reg_reg(dst, src)); | |
7218 ins_pipe(pipe_cmov_reg); | |
7219 %} | |
7220 | |
7221 // Conditional move | |
7222 instruct cmovN_regU(rRegN dst, rRegN src, rFlagsRegU cr, cmpOpU cop) | |
7223 %{ | |
7224 match(Set dst (CMoveN (Binary cop cr) (Binary dst src))); | |
7225 | |
7226 ins_cost(200); // XXX | |
7227 format %{ "cmovl$cop $dst, $src\t# unsigned, compressed ptr" %} | |
7228 opcode(0x0F, 0x40); | |
7229 ins_encode(REX_reg_reg(dst, src), enc_cmov(cop), reg_reg(dst, src)); | |
7230 ins_pipe(pipe_cmov_reg); | |
7143 %} | 7231 %} |
7144 | 7232 |
7145 // Conditional move | 7233 // Conditional move |
7146 instruct cmovP_reg(rRegP dst, rRegP src, rFlagsReg cr, cmpOp cop) | 7234 instruct cmovP_reg(rRegP dst, rRegP src, rFlagsReg cr, cmpOp cop) |
7147 %{ | 7235 %{ |
10860 format %{ "String Compare $str1, $str2 -> $result // XXX KILL RAX, RBX" %} | 10948 format %{ "String Compare $str1, $str2 -> $result // XXX KILL RAX, RBX" %} |
10861 ins_encode( enc_String_Compare() ); | 10949 ins_encode( enc_String_Compare() ); |
10862 ins_pipe( pipe_slow ); | 10950 ins_pipe( pipe_slow ); |
10863 %} | 10951 %} |
10864 | 10952 |
10953 // fast array equals | |
10954 instruct array_equals(rdi_RegP ary1, rsi_RegP ary2, rax_RegI tmp1, | |
10955 rbx_RegI tmp2, rcx_RegI result, rFlagsReg cr) %{ | |
10956 match(Set result (AryEq ary1 ary2)); | |
10957 effect(USE_KILL ary1, USE_KILL ary2, KILL tmp1, KILL tmp2, KILL cr); | |
10958 //ins_cost(300); | |
10959 | |
10960 format %{ "Array Equals $ary1,$ary2 -> $result // KILL RAX, RBX" %} | |
10961 ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, result) ); | |
10962 ins_pipe( pipe_slow ); | |
10963 %} | |
10964 | |
10865 //----------Control Flow Instructions------------------------------------------ | 10965 //----------Control Flow Instructions------------------------------------------ |
10866 // Signed compare Instructions | 10966 // Signed compare Instructions |
10867 | 10967 |
10868 // XXX more variants!! | 10968 // XXX more variants!! |
10869 instruct compI_rReg(rFlagsReg cr, rRegI op1, rRegI op2) | 10969 instruct compI_rReg(rFlagsReg cr, rRegI op1, rRegI op2) |
11053 ins_encode(REX_mem_wide(op), | 11153 ins_encode(REX_mem_wide(op), |
11054 OpcP, RM_opc_mem(0x00, op), Con_d32(0xFFFFFFFF)); | 11154 OpcP, RM_opc_mem(0x00, op), Con_d32(0xFFFFFFFF)); |
11055 ins_pipe(ialu_cr_reg_imm); | 11155 ins_pipe(ialu_cr_reg_imm); |
11056 %} | 11156 %} |
11057 | 11157 |
11158 | |
11159 instruct compN_rReg(rFlagsRegU cr, rRegN op1, rRegN op2) | |
11160 %{ | |
11161 match(Set cr (CmpN op1 op2)); | |
11162 | |
11163 format %{ "cmpl $op1, $op2\t# compressed ptr" %} | |
11164 ins_encode %{ __ cmpl(as_Register($op1$$reg), as_Register($op2$$reg)); %} | |
11165 ins_pipe(ialu_cr_reg_reg); | |
11166 %} | |
11167 | |
11168 instruct compN_rReg_mem(rFlagsRegU cr, rRegN src, memory mem) | |
11169 %{ | |
11170 match(Set cr (CmpN src (LoadN mem))); | |
11171 | |
11172 ins_cost(500); // XXX | |
11173 format %{ "cmpl $src, mem\t# compressed ptr" %} | |
11174 ins_encode %{ | |
11175 Address adr = build_address($mem$$base, $mem$$index, $mem$$scale, $mem$$disp); | |
11176 __ cmpl(as_Register($src$$reg), adr); | |
11177 %} | |
11178 ins_pipe(ialu_cr_reg_mem); | |
11179 %} | |
11180 | |
11058 instruct testN_reg(rFlagsReg cr, rRegN src, immN0 zero) %{ | 11181 instruct testN_reg(rFlagsReg cr, rRegN src, immN0 zero) %{ |
11059 match(Set cr (CmpN src zero)); | 11182 match(Set cr (CmpN src zero)); |
11060 | 11183 |
11061 format %{ "testl $src, $src" %} | 11184 format %{ "testl $src, $src\t# compressed ptr" %} |
11062 ins_encode %{ __ testl($src$$Register, $src$$Register); %} | 11185 ins_encode %{ __ testl($src$$Register, $src$$Register); %} |
11063 ins_pipe(ialu_cr_reg_imm); | 11186 ins_pipe(ialu_cr_reg_imm); |
11187 %} | |
11188 | |
11189 instruct testN_reg_mem(rFlagsReg cr, memory mem, immN0 zero) | |
11190 %{ | |
11191 match(Set cr (CmpN (LoadN mem) zero)); | |
11192 | |
11193 ins_cost(500); // XXX | |
11194 format %{ "testl $mem, 0xffffffff\t# compressed ptr" %} | |
11195 ins_encode %{ | |
11196 Address addr = build_address($mem$$base, $mem$$index, $mem$$scale, $mem$$disp); | |
11197 __ cmpl(addr, (int)0xFFFFFFFF); | |
11198 %} | |
11199 ins_pipe(ialu_cr_reg_mem); | |
11064 %} | 11200 %} |
11065 | 11201 |
11066 // Yanked all unsigned pointer compare operations. | 11202 // Yanked all unsigned pointer compare operations. |
11067 // Pointer compares are done with CmpP which is already unsigned. | 11203 // Pointer compares are done with CmpP which is already unsigned. |
11068 | 11204 |