| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
| 6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 4742 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4753 } | 4753 } |
| 4754 | 4754 |
| 4755 | 4755 |
| 4756 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4756 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4757 // Save ESP. | 4757 // Save ESP. |
| 4758 __ movl(locs()->temp(kSavedSpTempIndex).reg(), ESP); | 4758 __ movl(locs()->temp(kSavedSpTempIndex).reg(), ESP); |
| 4759 __ ReserveAlignedFrameSpace(kDoubleSize * InputCount()); | 4759 __ ReserveAlignedFrameSpace(kDoubleSize * InputCount()); |
| 4760 for (intptr_t i = 0; i < InputCount(); i++) { | 4760 for (intptr_t i = 0; i < InputCount(); i++) { |
| 4761 __ movsd(Address(ESP, kDoubleSize * i), locs()->in(i).fpu_reg()); | 4761 __ movsd(Address(ESP, kDoubleSize * i), locs()->in(i).fpu_reg()); |
| 4762 } | 4762 } |
| 4763 Label do_call, skip_call; | 4763 Label skip_call; |
| 4764 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { | 4764 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { |
| 4765 // Pseudo code: | 4765 // Pseudo code: |
| 4766 // if (exponent == 0.0) return 1.0; | 4766 // if (exponent == 0.0) return 1.0; |
| 4767 // if (base == 1.0) return 1.0; | 4767 // if (base == 1.0) return 1.0; |
| 4768 // if (base.isNaN || exponent.isNaN) { | 4768 // if (base.isNaN || exponent.isNaN) { |
| 4769 // return double.NAN; | 4769 // return double.NAN; |
| 4770 // } | 4770 // } |
| 4771 // if (base != -Infinity && exponent == 0.5) { |
| 4772 // if (base == 0.0) return 0.0; |
| 4773 // return sqrt(value); |
| 4774 // } |
| 4771 XmmRegister base = locs()->in(0).fpu_reg(); | 4775 XmmRegister base = locs()->in(0).fpu_reg(); |
| 4772 XmmRegister exp = locs()->in(1).fpu_reg(); | 4776 XmmRegister exp = locs()->in(1).fpu_reg(); |
| 4773 XmmRegister result = locs()->out(0).fpu_reg(); | 4777 XmmRegister result = locs()->out(0).fpu_reg(); |
| 4774 Register temp = locs()->temp(kObjectTempIndex).reg(); | 4778 Register temp = locs()->temp(kObjectTempIndex).reg(); |
| 4775 XmmRegister zero_temp = locs()->temp(kDoubleTempIndex).fpu_reg(); | 4779 XmmRegister zero_temp = locs()->temp(kDoubleTempIndex).fpu_reg(); |
| 4776 | 4780 |
| 4777 Label check_base_is_one; | 4781 Label do_call, check_base, return_nan; |
| 4778 // Check if exponent is 0.0 -> return 1.0; | |
| 4779 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(0))); | 4782 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(0))); |
| 4780 __ movsd(zero_temp, FieldAddress(temp, Double::value_offset())); | 4783 __ movsd(zero_temp, FieldAddress(temp, Double::value_offset())); |
| 4781 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(1))); | 4784 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(1))); |
| 4782 __ movsd(result, FieldAddress(temp, Double::value_offset())); | 4785 __ movsd(result, FieldAddress(temp, Double::value_offset())); |
| 4783 // 'result' contains 1.0. | 4786 |
| 4787 // Check if exponent is 0.0 -> return 1.0; |
| 4784 __ comisd(exp, zero_temp); | 4788 __ comisd(exp, zero_temp); |
| 4785 __ j(PARITY_EVEN, &check_base_is_one, Assembler::kNearJump); // NaN. | 4789 __ j(PARITY_EVEN, &check_base, Assembler::kNearJump); |
| 4786 __ j(EQUAL, &skip_call, Assembler::kNearJump); // exp is 0, result is 1.0. | 4790 __ j(EQUAL, &skip_call, Assembler::kNearJump); // 'result' is 1.0. |
| 4787 | 4791 |
| 4788 Label base_is_nan; | 4792 __ Bind(&check_base); |
| 4789 __ Bind(&check_base_is_one); | 4793 // Note: 'exp' could be NaN. |
| 4790 __ comisd(base, result); | 4794 __ comisd(base, result); |
| 4791 __ j(PARITY_EVEN, &base_is_nan, Assembler::kNearJump); | 4795 __ j(PARITY_EVEN, &return_nan, Assembler::kNearJump); |
| 4792 __ j(EQUAL, &skip_call, Assembler::kNearJump); // base and result are 1.0 | 4796 __ j(EQUAL, &skip_call, Assembler::kNearJump); |
| 4793 __ jmp(&do_call, Assembler::kNearJump); | 4797 // Note: 'base' could be NaN. |
| 4798 __ comisd(exp, base); |
| 4799 // Neither 'exp' nor 'base' is NaN. |
| 4800 __ j(PARITY_ODD, &do_call, Assembler::kNearJump); |
| 4801 // Return NaN. |
| 4802 __ Bind(&return_nan); |
| 4803 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(NAN))); |
| 4804 __ movsd(result, FieldAddress(temp, Double::value_offset())); |
| 4805 __ jmp(&skip_call); |
| 4794 | 4806 |
| 4795 __ Bind(&base_is_nan); | 4807 Label do_pow, return_zero; |
| 4796 // Returns NaN. | 4808 __ Bind(&do_call); |
| 4797 __ movsd(result, base); | 4809 |
| 4810 |
| 4811 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(-1.0/0.0))); |
| 4812 __ movsd(result, FieldAddress(temp, Double::value_offset())); |
| 4813 // base == -Infinity -> pow; |
| 4814 __ comisd(base, result); |
| 4815 __ j(EQUAL, &do_pow, Assembler::kNearJump); |
| 4816 |
| 4817 // Check if exponent is 0.5 -> sqrt(value). |
| 4818 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(0.5))); |
| 4819 __ movsd(result, FieldAddress(temp, Double::value_offset())); |
| 4820 __ comisd(exp, result); |
| 4821 __ j(NOT_EQUAL, &do_pow, Assembler::kNearJump); |
| 4822 |
| 4823 // base == 0 |
| 4824 __ comisd(base, zero_temp); |
| 4825 __ j(EQUAL, &return_zero, Assembler::kNearJump); |
| 4826 |
| 4827 __ sqrtsd(result, base); |
| 4798 __ jmp(&skip_call, Assembler::kNearJump); | 4828 __ jmp(&skip_call, Assembler::kNearJump); |
| 4799 // exp is Nan case is handled correctly in the C-library. | 4829 |
| 4830 __ Bind(&return_zero); |
| 4831 __ movsd(result, zero_temp); |
| 4832 __ jmp(&skip_call); |
| 4833 |
| 4834 __ Bind(&do_pow); |
| 4800 } | 4835 } |
| 4801 __ Bind(&do_call); | 4836 |
| 4802 __ CallRuntime(TargetFunction(), InputCount()); | 4837 __ CallRuntime(TargetFunction(), InputCount()); |
| 4803 __ fstpl(Address(ESP, 0)); | 4838 __ fstpl(Address(ESP, 0)); |
| 4804 __ movsd(locs()->out(0).fpu_reg(), Address(ESP, 0)); | 4839 __ movsd(locs()->out(0).fpu_reg(), Address(ESP, 0)); |
| 4805 __ Bind(&skip_call); | 4840 __ Bind(&skip_call); |
| 4806 // Restore ESP. | 4841 // Restore ESP. |
| 4807 __ movl(ESP, locs()->temp(kSavedSpTempIndex).reg()); | 4842 __ movl(ESP, locs()->temp(kSavedSpTempIndex).reg()); |
| 4808 } | 4843 } |
| 4809 | 4844 |
| 4810 | 4845 |
| 4811 LocationSummary* MergedMathInstr::MakeLocationSummary(bool opt) const { | 4846 LocationSummary* MergedMathInstr::MakeLocationSummary(bool opt) const { |
| (...skipping 991 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5803 PcDescriptors::kOther, | 5838 PcDescriptors::kOther, |
| 5804 locs()); | 5839 locs()); |
| 5805 __ Drop(ArgumentCount()); // Discard arguments. | 5840 __ Drop(ArgumentCount()); // Discard arguments. |
| 5806 } | 5841 } |
| 5807 | 5842 |
| 5808 } // namespace dart | 5843 } // namespace dart |
| 5809 | 5844 |
| 5810 #undef __ | 5845 #undef __ |
| 5811 | 5846 |
| 5812 #endif // defined TARGET_ARCH_IA32 | 5847 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |