Chromium Code Reviews| 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_ARM. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. |
| 6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
| 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 4912 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4923 } | 4923 } |
| 4924 result->AddTemp(Location::RegisterLocation(R3)); | 4924 result->AddTemp(Location::RegisterLocation(R3)); |
| 4925 #endif | 4925 #endif |
| 4926 result->set_out(0, Location::FpuRegisterLocation(Q0)); | 4926 result->set_out(0, Location::FpuRegisterLocation(Q0)); |
| 4927 return result; | 4927 return result; |
| 4928 } | 4928 } |
| 4929 | 4929 |
| 4930 | 4930 |
| 4931 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4931 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4932 // For pow-function return NaN if exponent is NaN. | 4932 // For pow-function return NaN if exponent is NaN. |
| 4933 Label do_call, skip_call; | 4933 Label skip_call; |
| 4934 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { | 4934 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { |
| 4935 // Pseudo code: | 4935 // Pseudo code: |
| 4936 // if (exponent == 0.0) return 0.0; | 4936 // if (exponent == 0.0) return 1.0; |
| 4937 // if (base == 1.0) return 1.0; | 4937 // if (base == 1.0) return 1.0; |
| 4938 // if (base.isNaN || exponent.isNaN) { | 4938 // if (base.isNaN || exponent.isNaN) { |
| 4939 // return double.NAN; | 4939 // return double.NAN; |
| 4940 // } | 4940 // } |
| 4941 // if (base != -Infinity && exponent == 0.5) { | |
| 4942 // if (base == 0.0) return 0.0; | |
| 4943 // return sqrt(value); | |
| 4944 // } | |
| 4941 DRegister base = EvenDRegisterOf(locs()->in(0).fpu_reg()); | 4945 DRegister base = EvenDRegisterOf(locs()->in(0).fpu_reg()); |
| 4942 DRegister exp = EvenDRegisterOf(locs()->in(1).fpu_reg()); | 4946 DRegister exp = EvenDRegisterOf(locs()->in(1).fpu_reg()); |
| 4943 DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); | 4947 DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); |
| 4944 Register temp = locs()->temp(0).reg(); | 4948 Register temp = locs()->temp(0).reg(); |
| 4945 DRegister saved_base = EvenDRegisterOf(locs()->temp(1).fpu_reg()); | 4949 DRegister saved_base = EvenDRegisterOf(locs()->temp(1).fpu_reg()); |
| 4946 ASSERT((base == result) && (result != saved_base)); | 4950 ASSERT((base == result) && (result != saved_base)); |
| 4947 Label check_base_is_one; | 4951 |
| 4948 // Check if exponent is 0.0 -> return 1.0; | 4952 Label do_call, check_base, return_nan; |
| 4949 __ vmovd(saved_base, base); | 4953 __ vmovd(saved_base, base); |
| 4950 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(0))); | 4954 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(0))); |
|
zra
2014/04/03 17:04:46
__ LoadDImmediate(DTMP, 0.0);
srdjan
2014/04/03 19:33:18
Done.
| |
| 4951 __ LoadDFromOffset(DTMP, temp, Double::value_offset() - kHeapObjectTag); | 4955 __ LoadDFromOffset(DTMP, temp, Double::value_offset() - kHeapObjectTag); |
| 4952 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(1))); | 4956 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(1))); |
|
zra
2014/04/03 17:04:46
__ LoadDImmediate(result, 1.0);
srdjan
2014/04/03 19:33:18
Done.
| |
| 4953 __ LoadDFromOffset(result, temp, Double::value_offset() - kHeapObjectTag); | 4957 __ LoadDFromOffset(result, temp, Double::value_offset() - kHeapObjectTag); |
| 4958 // exponent == 0.0 -> return 1.0; | |
| 4954 __ vcmpd(exp, DTMP); | 4959 __ vcmpd(exp, DTMP); |
| 4955 __ vmstat(); | 4960 __ vmstat(); |
| 4956 __ b(&check_base_is_one, VS); // NaN -> not zero. | 4961 __ b(&check_base, VS); // NaN -> check base. |
| 4957 __ b(&skip_call, EQ); // exp is 0.0, result is 1.0. | 4962 __ b(&skip_call, EQ); // exp is 0.0, result is 1.0. |
| 4958 | 4963 |
| 4959 __ Bind(&check_base_is_one); | 4964 __ Bind(&check_base); |
| 4965 // Note: 'exp' could be NaN. | |
| 4966 // base == 1.0 -> return 1.0; | |
| 4960 __ vcmpd(saved_base, result); | 4967 __ vcmpd(saved_base, result); |
| 4961 __ vmstat(); | 4968 __ vmstat(); |
| 4962 __ vmovd(result, saved_base, VS); // base is NaN, return NaN. | 4969 __ b(&return_nan, VS); |
| 4963 __ b(&skip_call, VS); | 4970 __ b(&skip_call, EQ); // base is 1.0, result is 1.0. |
| 4964 __ b(&skip_call, EQ); // base and result are 1.0. | 4971 |
| 4972 __ vcmpd(saved_base, exp); | |
| 4973 __ b(&do_call, VC); // // Neither 'exp' nor 'base' is NaN. | |
| 4974 | |
| 4975 __ Bind(&return_nan); | |
| 4976 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(NAN))); | |
|
zra
2014/04/03 17:04:46
__ LoadDImmediate(result, NAN);
srdjan
2014/04/03 19:33:18
Done.
| |
| 4977 __ LoadDFromOffset(result, temp, Double::value_offset() - kHeapObjectTag); | |
| 4978 __ b(&skip_call); | |
| 4979 | |
| 4980 Label do_pow, return_zero; | |
| 4981 __ Bind(&do_call); | |
|
zra
2014/04/03 17:04:46
Maybe rename label since we're checking for 0.5 no
srdjan
2014/04/03 19:33:18
Renamed to try_sqrt
| |
| 4982 | |
| 4983 // Before calling check if we could use sqrt instead of pow. | |
|
zra
2014/04/03 17:04:46
Before calling,
srdjan
2014/04/03 19:33:18
Done.
| |
| 4984 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(-INFINITY))); | |
|
zra
2014/04/03 17:04:46
__ LoadDImmediate(result, -INFINITY);
srdjan
2014/04/03 19:33:18
Done.
| |
| 4985 __ LoadDFromOffset(result, temp, Double::value_offset() - kHeapObjectTag); | |
| 4986 // base == -Infinity -> call pow; | |
| 4987 __ vcmpd(saved_base, result); | |
| 4988 __ b(&do_pow, EQ); | |
| 4989 | |
| 4990 // exponent == 0.5 ? | |
| 4991 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(0.5))); | |
|
zra
2014/04/03 17:04:46
__ LoadDImmediate(result, 0.5);
srdjan
2014/04/03 19:33:18
Done.
| |
| 4992 __ LoadDFromOffset(result, temp, Double::value_offset() - kHeapObjectTag); | |
| 4993 __ vcmpd(exp, result); | |
| 4994 __ b(&do_pow, NE); | |
| 4995 | |
| 4996 // base == 0 -> return 0; | |
| 4997 __ vcmpd(base, DTMP); | |
| 4998 __ b(&return_zero, EQ); | |
| 4999 | |
| 5000 __ vsqrtd(result, saved_base); | |
| 5001 __ b(&skip_call); | |
| 5002 | |
| 5003 __ Bind(&return_zero); | |
| 5004 __ vmovd(result, DTMP); | |
| 5005 __ b(&skip_call); | |
| 5006 | |
| 5007 __ Bind(&do_pow); | |
| 4965 __ vmovd(base, saved_base); // Restore base. | 5008 __ vmovd(base, saved_base); // Restore base. |
| 4966 } | 5009 } |
| 4967 __ Bind(&do_call); | 5010 |
| 4968 if (InputCount() == 2) { | 5011 if (InputCount() == 2) { |
| 4969 // Args must be in D0 and D1, so move arg from Q1(== D3:D2) to D1. | 5012 // Args must be in D0 and D1, so move arg from Q1(== D3:D2) to D1. |
| 4970 __ vmovd(D1, D2); | 5013 __ vmovd(D1, D2); |
| 4971 } | 5014 } |
| 4972 #if defined(ARM_FLOAT_ABI_HARD) | 5015 #if defined(ARM_FLOAT_ABI_HARD) |
| 4973 __ CallRuntime(TargetFunction(), InputCount()); | 5016 __ CallRuntime(TargetFunction(), InputCount()); |
| 4974 #else | 5017 #else |
| 4975 // If the ABI is not "hardfp", then we have to move the double arguments | 5018 // If the ABI is not "hardfp", then we have to move the double arguments |
| 4976 // to the integer registers, and take the results from the integer | 5019 // to the integer registers, and take the results from the integer |
| 4977 // registers. | 5020 // registers. |
| (...skipping 845 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5823 compiler->GenerateCall(token_pos(), | 5866 compiler->GenerateCall(token_pos(), |
| 5824 &label, | 5867 &label, |
| 5825 PcDescriptors::kOther, | 5868 PcDescriptors::kOther, |
| 5826 locs()); | 5869 locs()); |
| 5827 __ Drop(ArgumentCount()); // Discard arguments. | 5870 __ Drop(ArgumentCount()); // Discard arguments. |
| 5828 } | 5871 } |
| 5829 | 5872 |
| 5830 } // namespace dart | 5873 } // namespace dart |
| 5831 | 5874 |
| 5832 #endif // defined TARGET_ARCH_ARM | 5875 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |