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 |