| 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 611 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 622 } else { | 622 } else { |
| 623 __ mov(result_reg, exponent_operand); | 623 __ mov(result_reg, exponent_operand); |
| 624 } | 624 } |
| 625 __ and_(result_reg, | 625 __ and_(result_reg, |
| 626 Immediate(static_cast<uint32_t>(Double::kSignificandMask >> 32))); | 626 Immediate(static_cast<uint32_t>(Double::kSignificandMask >> 32))); |
| 627 __ add(result_reg, | 627 __ add(result_reg, |
| 628 Immediate(static_cast<uint32_t>(Double::kHiddenBit >> 32))); | 628 Immediate(static_cast<uint32_t>(Double::kHiddenBit >> 32))); |
| 629 __ shrd(result_reg, scratch1); | 629 __ shrd(result_reg, scratch1); |
| 630 __ shr_cl(result_reg); | 630 __ shr_cl(result_reg); |
| 631 __ test(ecx, Immediate(32)); | 631 __ test(ecx, Immediate(32)); |
| 632 if (CpuFeatures::IsSupported(CMOV)) { | 632 __ cmov(not_equal, scratch1, result_reg); |
| 633 CpuFeatureScope use_cmov(masm, CMOV); | |
| 634 __ cmov(not_equal, scratch1, result_reg); | |
| 635 } else { | |
| 636 Label skip_mov; | |
| 637 __ j(equal, &skip_mov, Label::kNear); | |
| 638 __ mov(scratch1, result_reg); | |
| 639 __ bind(&skip_mov); | |
| 640 } | |
| 641 } | 633 } |
| 642 | 634 |
| 643 // If the double was negative, negate the integer result. | 635 // If the double was negative, negate the integer result. |
| 644 __ bind(&check_negative); | 636 __ bind(&check_negative); |
| 645 __ mov(result_reg, scratch1); | 637 __ mov(result_reg, scratch1); |
| 646 __ neg(result_reg); | 638 __ neg(result_reg); |
| 647 if (stash_exponent_copy) { | 639 if (stash_exponent_copy) { |
| 648 __ cmp(MemOperand(esp, 0), Immediate(0)); | 640 __ cmp(MemOperand(esp, 0), Immediate(0)); |
| 649 } else { | 641 } else { |
| 650 __ cmp(exponent_operand, Immediate(0)); | 642 __ cmp(exponent_operand, Immediate(0)); |
| 651 } | 643 } |
| 652 if (CpuFeatures::IsSupported(CMOV)) { | |
| 653 CpuFeatureScope use_cmov(masm, CMOV); | |
| 654 __ cmov(greater, result_reg, scratch1); | 644 __ cmov(greater, result_reg, scratch1); |
| 655 } else { | |
| 656 Label skip_mov; | |
| 657 __ j(less_equal, &skip_mov, Label::kNear); | |
| 658 __ mov(result_reg, scratch1); | |
| 659 __ bind(&skip_mov); | |
| 660 } | |
| 661 | 645 |
| 662 // Restore registers | 646 // Restore registers |
| 663 __ bind(&done); | 647 __ bind(&done); |
| 664 if (stash_exponent_copy) { | 648 if (stash_exponent_copy) { |
| 665 __ add(esp, Immediate(kDoubleSize / 2)); | 649 __ add(esp, Immediate(kDoubleSize / 2)); |
| 666 } | 650 } |
| 667 __ bind(&done_no_stash); | 651 __ bind(&done_no_stash); |
| 668 if (!final_result_reg.is(result_reg)) { | 652 if (!final_result_reg.is(result_reg)) { |
| 669 ASSERT(final_result_reg.is(ecx)); | 653 ASSERT(final_result_reg.is(ecx)); |
| 670 __ mov(final_result_reg, result_reg); | 654 __ mov(final_result_reg, result_reg); |
| (...skipping 1390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2061 // Generate the number comparison code. | 2045 // Generate the number comparison code. |
| 2062 Label non_number_comparison; | 2046 Label non_number_comparison; |
| 2063 Label unordered; | 2047 Label unordered; |
| 2064 __ bind(&generic_heap_number_comparison); | 2048 __ bind(&generic_heap_number_comparison); |
| 2065 | 2049 |
| 2066 FloatingPointHelper::LoadSSE2Operands(masm, &non_number_comparison); | 2050 FloatingPointHelper::LoadSSE2Operands(masm, &non_number_comparison); |
| 2067 __ ucomisd(xmm0, xmm1); | 2051 __ ucomisd(xmm0, xmm1); |
| 2068 // Don't base result on EFLAGS when a NaN is involved. | 2052 // Don't base result on EFLAGS when a NaN is involved. |
| 2069 __ j(parity_even, &unordered, Label::kNear); | 2053 __ j(parity_even, &unordered, Label::kNear); |
| 2070 | 2054 |
| 2071 if (CpuFeatures::IsSupported(CMOV)) { | 2055 __ mov(eax, 0); // equal |
| 2072 CpuFeatureScope use_cmov(masm, CMOV); | 2056 __ mov(ecx, Immediate(Smi::FromInt(1))); |
| 2073 // Return a result of -1, 0, or 1, based on EFLAGS. | 2057 __ cmov(above, eax, ecx); |
| 2074 __ mov(eax, 0); // equal | 2058 __ mov(ecx, Immediate(Smi::FromInt(-1))); |
| 2075 __ mov(ecx, Immediate(Smi::FromInt(1))); | 2059 __ cmov(below, eax, ecx); |
| 2076 __ cmov(above, eax, ecx); | 2060 __ ret(0); |
| 2077 __ mov(ecx, Immediate(Smi::FromInt(-1))); | |
| 2078 __ cmov(below, eax, ecx); | |
| 2079 __ ret(0); | |
| 2080 } else { | |
| 2081 Label below_label, above_label; | |
| 2082 // Return a result of -1, 0, or 1, based on EFLAGS. | |
| 2083 __ j(below, &below_label, Label::kNear); | |
| 2084 __ j(above, &above_label, Label::kNear); | |
| 2085 | |
| 2086 __ Move(eax, Immediate(0)); | |
| 2087 __ ret(0); | |
| 2088 | |
| 2089 __ bind(&below_label); | |
| 2090 __ mov(eax, Immediate(Smi::FromInt(-1))); | |
| 2091 __ ret(0); | |
| 2092 | |
| 2093 __ bind(&above_label); | |
| 2094 __ mov(eax, Immediate(Smi::FromInt(1))); | |
| 2095 __ ret(0); | |
| 2096 } | |
| 2097 | 2061 |
| 2098 // If one of the numbers was NaN, then the result is always false. | 2062 // If one of the numbers was NaN, then the result is always false. |
| 2099 // The cc is never not-equal. | 2063 // The cc is never not-equal. |
| 2100 __ bind(&unordered); | 2064 __ bind(&unordered); |
| 2101 ASSERT(cc != not_equal); | 2065 ASSERT(cc != not_equal); |
| 2102 if (cc == less || cc == less_equal) { | 2066 if (cc == less || cc == less_equal) { |
| 2103 __ mov(eax, Immediate(Smi::FromInt(1))); | 2067 __ mov(eax, Immediate(Smi::FromInt(1))); |
| 2104 } else { | 2068 } else { |
| 2105 __ mov(eax, Immediate(Smi::FromInt(-1))); | 2069 __ mov(eax, Immediate(Smi::FromInt(-1))); |
| 2106 } | 2070 } |
| (...skipping 1662 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3769 Label unordered, maybe_undefined1, maybe_undefined2; | 3733 Label unordered, maybe_undefined1, maybe_undefined2; |
| 3770 Label miss; | 3734 Label miss; |
| 3771 | 3735 |
| 3772 if (left_ == CompareIC::SMI) { | 3736 if (left_ == CompareIC::SMI) { |
| 3773 __ JumpIfNotSmi(edx, &miss); | 3737 __ JumpIfNotSmi(edx, &miss); |
| 3774 } | 3738 } |
| 3775 if (right_ == CompareIC::SMI) { | 3739 if (right_ == CompareIC::SMI) { |
| 3776 __ JumpIfNotSmi(eax, &miss); | 3740 __ JumpIfNotSmi(eax, &miss); |
| 3777 } | 3741 } |
| 3778 | 3742 |
| 3779 // Inlining the double comparison and falling back to the general compare | 3743 // Load left and right operand. |
| 3780 // stub if NaN is involved or SSE2 or CMOV is unsupported. | 3744 Label done, left, left_smi, right_smi; |
| 3781 if (CpuFeatures::IsSupported(CMOV)) { | 3745 __ JumpIfSmi(eax, &right_smi, Label::kNear); |
| 3782 CpuFeatureScope scope2(masm, CMOV); | 3746 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), |
| 3747 isolate()->factory()->heap_number_map()); |
| 3748 __ j(not_equal, &maybe_undefined1, Label::kNear); |
| 3749 __ movsd(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); |
| 3750 __ jmp(&left, Label::kNear); |
| 3751 __ bind(&right_smi); |
| 3752 __ mov(ecx, eax); // Can't clobber eax because we can still jump away. |
| 3753 __ SmiUntag(ecx); |
| 3754 __ Cvtsi2sd(xmm1, ecx); |
| 3783 | 3755 |
| 3784 // Load left and right operand. | 3756 __ bind(&left); |
| 3785 Label done, left, left_smi, right_smi; | 3757 __ JumpIfSmi(edx, &left_smi, Label::kNear); |
| 3786 __ JumpIfSmi(eax, &right_smi, Label::kNear); | 3758 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
| 3787 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), | 3759 isolate()->factory()->heap_number_map()); |
| 3788 isolate()->factory()->heap_number_map()); | 3760 __ j(not_equal, &maybe_undefined2, Label::kNear); |
| 3789 __ j(not_equal, &maybe_undefined1, Label::kNear); | 3761 __ movsd(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); |
| 3790 __ movsd(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); | 3762 __ jmp(&done); |
| 3791 __ jmp(&left, Label::kNear); | 3763 __ bind(&left_smi); |
| 3792 __ bind(&right_smi); | 3764 __ mov(ecx, edx); // Can't clobber edx because we can still jump away. |
| 3793 __ mov(ecx, eax); // Can't clobber eax because we can still jump away. | 3765 __ SmiUntag(ecx); |
| 3794 __ SmiUntag(ecx); | 3766 __ Cvtsi2sd(xmm0, ecx); |
| 3795 __ Cvtsi2sd(xmm1, ecx); | |
| 3796 | 3767 |
| 3797 __ bind(&left); | 3768 __ bind(&done); |
| 3798 __ JumpIfSmi(edx, &left_smi, Label::kNear); | 3769 // Compare operands. |
| 3799 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 3770 __ ucomisd(xmm0, xmm1); |
| 3800 isolate()->factory()->heap_number_map()); | |
| 3801 __ j(not_equal, &maybe_undefined2, Label::kNear); | |
| 3802 __ movsd(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); | |
| 3803 __ jmp(&done); | |
| 3804 __ bind(&left_smi); | |
| 3805 __ mov(ecx, edx); // Can't clobber edx because we can still jump away. | |
| 3806 __ SmiUntag(ecx); | |
| 3807 __ Cvtsi2sd(xmm0, ecx); | |
| 3808 | 3771 |
| 3809 __ bind(&done); | 3772 // Don't base result on EFLAGS when a NaN is involved. |
| 3810 // Compare operands. | 3773 __ j(parity_even, &unordered, Label::kNear); |
| 3811 __ ucomisd(xmm0, xmm1); | |
| 3812 | 3774 |
| 3813 // Don't base result on EFLAGS when a NaN is involved. | 3775 // Return a result of -1, 0, or 1, based on EFLAGS. |
| 3814 __ j(parity_even, &unordered, Label::kNear); | 3776 // Performing mov, because xor would destroy the flag register. |
| 3815 | 3777 __ mov(eax, 0); // equal |
| 3816 // Return a result of -1, 0, or 1, based on EFLAGS. | 3778 __ mov(ecx, Immediate(Smi::FromInt(1))); |
| 3817 // Performing mov, because xor would destroy the flag register. | 3779 __ cmov(above, eax, ecx); |
| 3818 __ mov(eax, 0); // equal | 3780 __ mov(ecx, Immediate(Smi::FromInt(-1))); |
| 3819 __ mov(ecx, Immediate(Smi::FromInt(1))); | 3781 __ cmov(below, eax, ecx); |
| 3820 __ cmov(above, eax, ecx); | 3782 __ ret(0); |
| 3821 __ mov(ecx, Immediate(Smi::FromInt(-1))); | |
| 3822 __ cmov(below, eax, ecx); | |
| 3823 __ ret(0); | |
| 3824 } else { | |
| 3825 __ mov(ecx, edx); | |
| 3826 __ and_(ecx, eax); | |
| 3827 __ JumpIfSmi(ecx, &generic_stub, Label::kNear); | |
| 3828 | |
| 3829 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), | |
| 3830 isolate()->factory()->heap_number_map()); | |
| 3831 __ j(not_equal, &maybe_undefined1, Label::kNear); | |
| 3832 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | |
| 3833 isolate()->factory()->heap_number_map()); | |
| 3834 __ j(not_equal, &maybe_undefined2, Label::kNear); | |
| 3835 } | |
| 3836 | 3783 |
| 3837 __ bind(&unordered); | 3784 __ bind(&unordered); |
| 3838 __ bind(&generic_stub); | 3785 __ bind(&generic_stub); |
| 3839 ICCompareStub stub(isolate(), op_, CompareIC::GENERIC, CompareIC::GENERIC, | 3786 ICCompareStub stub(isolate(), op_, CompareIC::GENERIC, CompareIC::GENERIC, |
| 3840 CompareIC::GENERIC); | 3787 CompareIC::GENERIC); |
| 3841 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); | 3788 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); |
| 3842 | 3789 |
| 3843 __ bind(&maybe_undefined1); | 3790 __ bind(&maybe_undefined1); |
| 3844 if (Token::IsOrderedRelationalCompareOp(op_)) { | 3791 if (Token::IsOrderedRelationalCompareOp(op_)) { |
| 3845 __ cmp(eax, Immediate(isolate()->factory()->undefined_value())); | 3792 __ cmp(eax, Immediate(isolate()->factory()->undefined_value())); |
| (...skipping 1282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5128 Operand(ebp, 7 * kPointerSize), | 5075 Operand(ebp, 7 * kPointerSize), |
| 5129 NULL); | 5076 NULL); |
| 5130 } | 5077 } |
| 5131 | 5078 |
| 5132 | 5079 |
| 5133 #undef __ | 5080 #undef __ |
| 5134 | 5081 |
| 5135 } } // namespace v8::internal | 5082 } } // namespace v8::internal |
| 5136 | 5083 |
| 5137 #endif // V8_TARGET_ARCH_IA32 | 5084 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |