| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "v8.h" | 5 #include "v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_IA32 | 7 #if V8_TARGET_ARCH_IA32 |
| 8 | 8 |
| 9 #include "bootstrapper.h" | 9 #include "bootstrapper.h" |
| 10 #include "code-stubs.h" | 10 #include "code-stubs.h" |
| (...skipping 597 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 608 } else { | 608 } else { |
| 609 __ mov(result_reg, exponent_operand); | 609 __ mov(result_reg, exponent_operand); |
| 610 } | 610 } |
| 611 __ and_(result_reg, | 611 __ and_(result_reg, |
| 612 Immediate(static_cast<uint32_t>(Double::kSignificandMask >> 32))); | 612 Immediate(static_cast<uint32_t>(Double::kSignificandMask >> 32))); |
| 613 __ add(result_reg, | 613 __ add(result_reg, |
| 614 Immediate(static_cast<uint32_t>(Double::kHiddenBit >> 32))); | 614 Immediate(static_cast<uint32_t>(Double::kHiddenBit >> 32))); |
| 615 __ shrd(result_reg, scratch1); | 615 __ shrd(result_reg, scratch1); |
| 616 __ shr_cl(result_reg); | 616 __ shr_cl(result_reg); |
| 617 __ test(ecx, Immediate(32)); | 617 __ test(ecx, Immediate(32)); |
| 618 if (CpuFeatures::IsSupported(CMOV)) { | 618 __ cmov(not_equal, scratch1, result_reg); |
| 619 CpuFeatureScope use_cmov(masm, CMOV); | |
| 620 __ cmov(not_equal, scratch1, result_reg); | |
| 621 } else { | |
| 622 Label skip_mov; | |
| 623 __ j(equal, &skip_mov, Label::kNear); | |
| 624 __ mov(scratch1, result_reg); | |
| 625 __ bind(&skip_mov); | |
| 626 } | |
| 627 } | 619 } |
| 628 | 620 |
| 629 // If the double was negative, negate the integer result. | 621 // If the double was negative, negate the integer result. |
| 630 __ bind(&check_negative); | 622 __ bind(&check_negative); |
| 631 __ mov(result_reg, scratch1); | 623 __ mov(result_reg, scratch1); |
| 632 __ neg(result_reg); | 624 __ neg(result_reg); |
| 633 if (stash_exponent_copy) { | 625 if (stash_exponent_copy) { |
| 634 __ cmp(MemOperand(esp, 0), Immediate(0)); | 626 __ cmp(MemOperand(esp, 0), Immediate(0)); |
| 635 } else { | 627 } else { |
| 636 __ cmp(exponent_operand, Immediate(0)); | 628 __ cmp(exponent_operand, Immediate(0)); |
| 637 } | 629 } |
| 638 if (CpuFeatures::IsSupported(CMOV)) { | 630 __ cmov(greater, result_reg, scratch1); |
| 639 CpuFeatureScope use_cmov(masm, CMOV); | |
| 640 __ cmov(greater, result_reg, scratch1); | |
| 641 } else { | |
| 642 Label skip_mov; | |
| 643 __ j(less_equal, &skip_mov, Label::kNear); | |
| 644 __ mov(result_reg, scratch1); | |
| 645 __ bind(&skip_mov); | |
| 646 } | |
| 647 | 631 |
| 648 // Restore registers | 632 // Restore registers |
| 649 __ bind(&done); | 633 __ bind(&done); |
| 650 if (stash_exponent_copy) { | 634 if (stash_exponent_copy) { |
| 651 __ add(esp, Immediate(kDoubleSize / 2)); | 635 __ add(esp, Immediate(kDoubleSize / 2)); |
| 652 } | 636 } |
| 653 __ bind(&done_no_stash); | 637 __ bind(&done_no_stash); |
| 654 if (!final_result_reg.is(result_reg)) { | 638 if (!final_result_reg.is(result_reg)) { |
| 655 ASSERT(final_result_reg.is(ecx)); | 639 ASSERT(final_result_reg.is(ecx)); |
| 656 __ mov(final_result_reg, result_reg); | 640 __ mov(final_result_reg, result_reg); |
| (...skipping 1390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2047 // Generate the number comparison code. | 2031 // Generate the number comparison code. |
| 2048 Label non_number_comparison; | 2032 Label non_number_comparison; |
| 2049 Label unordered; | 2033 Label unordered; |
| 2050 __ bind(&generic_heap_number_comparison); | 2034 __ bind(&generic_heap_number_comparison); |
| 2051 | 2035 |
| 2052 FloatingPointHelper::LoadSSE2Operands(masm, &non_number_comparison); | 2036 FloatingPointHelper::LoadSSE2Operands(masm, &non_number_comparison); |
| 2053 __ ucomisd(xmm0, xmm1); | 2037 __ ucomisd(xmm0, xmm1); |
| 2054 // Don't base result on EFLAGS when a NaN is involved. | 2038 // Don't base result on EFLAGS when a NaN is involved. |
| 2055 __ j(parity_even, &unordered, Label::kNear); | 2039 __ j(parity_even, &unordered, Label::kNear); |
| 2056 | 2040 |
| 2057 if (CpuFeatures::IsSupported(CMOV)) { | 2041 // Return a result of -1, 0, or 1, based on EFLAGS. |
| 2058 CpuFeatureScope use_cmov(masm, CMOV); | 2042 __ mov(eax, 0); // equal |
| 2059 // Return a result of -1, 0, or 1, based on EFLAGS. | 2043 __ mov(ecx, Immediate(Smi::FromInt(1))); |
| 2060 __ mov(eax, 0); // equal | 2044 __ cmov(above, eax, ecx); |
| 2061 __ mov(ecx, Immediate(Smi::FromInt(1))); | 2045 __ mov(ecx, Immediate(Smi::FromInt(-1))); |
| 2062 __ cmov(above, eax, ecx); | 2046 __ cmov(below, eax, ecx); |
| 2063 __ mov(ecx, Immediate(Smi::FromInt(-1))); | 2047 __ ret(0); |
| 2064 __ cmov(below, eax, ecx); | |
| 2065 __ ret(0); | |
| 2066 } else { | |
| 2067 Label below_label, above_label; | |
| 2068 // Return a result of -1, 0, or 1, based on EFLAGS. | |
| 2069 __ j(below, &below_label, Label::kNear); | |
| 2070 __ j(above, &above_label, Label::kNear); | |
| 2071 | |
| 2072 __ Move(eax, Immediate(0)); | |
| 2073 __ ret(0); | |
| 2074 | |
| 2075 __ bind(&below_label); | |
| 2076 __ mov(eax, Immediate(Smi::FromInt(-1))); | |
| 2077 __ ret(0); | |
| 2078 | |
| 2079 __ bind(&above_label); | |
| 2080 __ mov(eax, Immediate(Smi::FromInt(1))); | |
| 2081 __ ret(0); | |
| 2082 } | |
| 2083 | 2048 |
| 2084 // If one of the numbers was NaN, then the result is always false. | 2049 // If one of the numbers was NaN, then the result is always false. |
| 2085 // The cc is never not-equal. | 2050 // The cc is never not-equal. |
| 2086 __ bind(&unordered); | 2051 __ bind(&unordered); |
| 2087 ASSERT(cc != not_equal); | 2052 ASSERT(cc != not_equal); |
| 2088 if (cc == less || cc == less_equal) { | 2053 if (cc == less || cc == less_equal) { |
| 2089 __ mov(eax, Immediate(Smi::FromInt(1))); | 2054 __ mov(eax, Immediate(Smi::FromInt(1))); |
| 2090 } else { | 2055 } else { |
| 2091 __ mov(eax, Immediate(Smi::FromInt(-1))); | 2056 __ mov(eax, Immediate(Smi::FromInt(-1))); |
| 2092 } | 2057 } |
| (...skipping 1664 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3757 | 3722 |
| 3758 if (left_ == CompareIC::SMI) { | 3723 if (left_ == CompareIC::SMI) { |
| 3759 __ JumpIfNotSmi(edx, &miss); | 3724 __ JumpIfNotSmi(edx, &miss); |
| 3760 } | 3725 } |
| 3761 if (right_ == CompareIC::SMI) { | 3726 if (right_ == CompareIC::SMI) { |
| 3762 __ JumpIfNotSmi(eax, &miss); | 3727 __ JumpIfNotSmi(eax, &miss); |
| 3763 } | 3728 } |
| 3764 | 3729 |
| 3765 // Inlining the double comparison and falling back to the general compare | 3730 // Inlining the double comparison and falling back to the general compare |
| 3766 // stub if NaN is involved or SSE2 or CMOV is unsupported. | 3731 // stub if NaN is involved or SSE2 or CMOV is unsupported. |
| 3767 if (CpuFeatures::IsSupported(CMOV)) { | 3732 // Load left and right operand. |
| 3768 CpuFeatureScope scope2(masm, CMOV); | 3733 Label done, left, left_smi, right_smi; |
| 3734 __ JumpIfSmi(eax, &right_smi, Label::kNear); |
| 3735 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), |
| 3736 isolate()->factory()->heap_number_map()); |
| 3737 __ j(not_equal, &maybe_undefined1, Label::kNear); |
| 3738 __ movsd(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); |
| 3739 __ jmp(&left, Label::kNear); |
| 3740 __ bind(&right_smi); |
| 3741 __ mov(ecx, eax); // Can't clobber eax because we can still jump away. |
| 3742 __ SmiUntag(ecx); |
| 3743 __ Cvtsi2sd(xmm1, ecx); |
| 3769 | 3744 |
| 3770 // Load left and right operand. | 3745 __ bind(&left); |
| 3771 Label done, left, left_smi, right_smi; | 3746 __ JumpIfSmi(edx, &left_smi, Label::kNear); |
| 3772 __ JumpIfSmi(eax, &right_smi, Label::kNear); | 3747 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
| 3773 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), | 3748 isolate()->factory()->heap_number_map()); |
| 3774 isolate()->factory()->heap_number_map()); | 3749 __ j(not_equal, &maybe_undefined2, Label::kNear); |
| 3775 __ j(not_equal, &maybe_undefined1, Label::kNear); | 3750 __ movsd(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); |
| 3776 __ movsd(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); | 3751 __ jmp(&done); |
| 3777 __ jmp(&left, Label::kNear); | 3752 __ bind(&left_smi); |
| 3778 __ bind(&right_smi); | 3753 __ mov(ecx, edx); // Can't clobber edx because we can still jump away. |
| 3779 __ mov(ecx, eax); // Can't clobber eax because we can still jump away. | 3754 __ SmiUntag(ecx); |
| 3780 __ SmiUntag(ecx); | 3755 __ Cvtsi2sd(xmm0, ecx); |
| 3781 __ Cvtsi2sd(xmm1, ecx); | |
| 3782 | 3756 |
| 3783 __ bind(&left); | 3757 __ bind(&done); |
| 3784 __ JumpIfSmi(edx, &left_smi, Label::kNear); | 3758 // Compare operands. |
| 3785 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 3759 __ ucomisd(xmm0, xmm1); |
| 3786 isolate()->factory()->heap_number_map()); | |
| 3787 __ j(not_equal, &maybe_undefined2, Label::kNear); | |
| 3788 __ movsd(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); | |
| 3789 __ jmp(&done); | |
| 3790 __ bind(&left_smi); | |
| 3791 __ mov(ecx, edx); // Can't clobber edx because we can still jump away. | |
| 3792 __ SmiUntag(ecx); | |
| 3793 __ Cvtsi2sd(xmm0, ecx); | |
| 3794 | 3760 |
| 3795 __ bind(&done); | 3761 // Don't base result on EFLAGS when a NaN is involved. |
| 3796 // Compare operands. | 3762 __ j(parity_even, &unordered, Label::kNear); |
| 3797 __ ucomisd(xmm0, xmm1); | |
| 3798 | 3763 |
| 3799 // Don't base result on EFLAGS when a NaN is involved. | 3764 // Return a result of -1, 0, or 1, based on EFLAGS. |
| 3800 __ j(parity_even, &unordered, Label::kNear); | 3765 // Performing mov, because xor would destroy the flag register. |
| 3801 | 3766 __ mov(eax, 0); // equal |
| 3802 // Return a result of -1, 0, or 1, based on EFLAGS. | 3767 __ mov(ecx, Immediate(Smi::FromInt(1))); |
| 3803 // Performing mov, because xor would destroy the flag register. | 3768 __ cmov(above, eax, ecx); |
| 3804 __ mov(eax, 0); // equal | 3769 __ mov(ecx, Immediate(Smi::FromInt(-1))); |
| 3805 __ mov(ecx, Immediate(Smi::FromInt(1))); | 3770 __ cmov(below, eax, ecx); |
| 3806 __ cmov(above, eax, ecx); | 3771 __ ret(0); |
| 3807 __ mov(ecx, Immediate(Smi::FromInt(-1))); | |
| 3808 __ cmov(below, eax, ecx); | |
| 3809 __ ret(0); | |
| 3810 } else { | |
| 3811 __ mov(ecx, edx); | |
| 3812 __ and_(ecx, eax); | |
| 3813 __ JumpIfSmi(ecx, &generic_stub, Label::kNear); | |
| 3814 | |
| 3815 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), | |
| 3816 isolate()->factory()->heap_number_map()); | |
| 3817 __ j(not_equal, &maybe_undefined1, Label::kNear); | |
| 3818 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | |
| 3819 isolate()->factory()->heap_number_map()); | |
| 3820 __ j(not_equal, &maybe_undefined2, Label::kNear); | |
| 3821 } | |
| 3822 | 3772 |
| 3823 __ bind(&unordered); | 3773 __ bind(&unordered); |
| 3824 __ bind(&generic_stub); | 3774 __ bind(&generic_stub); |
| 3825 ICCompareStub stub(isolate(), op_, CompareIC::GENERIC, CompareIC::GENERIC, | 3775 ICCompareStub stub(isolate(), op_, CompareIC::GENERIC, CompareIC::GENERIC, |
| 3826 CompareIC::GENERIC); | 3776 CompareIC::GENERIC); |
| 3827 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); | 3777 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); |
| 3828 | 3778 |
| 3829 __ bind(&maybe_undefined1); | 3779 __ bind(&maybe_undefined1); |
| 3830 if (Token::IsOrderedRelationalCompareOp(op_)) { | 3780 if (Token::IsOrderedRelationalCompareOp(op_)) { |
| 3831 __ cmp(eax, Immediate(isolate()->factory()->undefined_value())); | 3781 __ cmp(eax, Immediate(isolate()->factory()->undefined_value())); |
| (...skipping 1282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5114 Operand(ebp, 7 * kPointerSize), | 5064 Operand(ebp, 7 * kPointerSize), |
| 5115 NULL); | 5065 NULL); |
| 5116 } | 5066 } |
| 5117 | 5067 |
| 5118 | 5068 |
| 5119 #undef __ | 5069 #undef __ |
| 5120 | 5070 |
| 5121 } } // namespace v8::internal | 5071 } } // namespace v8::internal |
| 5122 | 5072 |
| 5123 #endif // V8_TARGET_ARCH_IA32 | 5073 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |