| 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 #if V8_TARGET_ARCH_MIPS | 5 #if V8_TARGET_ARCH_MIPS |
| 6 | 6 |
| 7 #include "src/code-stubs.h" | 7 #include "src/code-stubs.h" |
| 8 #include "src/api-arguments.h" | 8 #include "src/api-arguments.h" |
| 9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
| 10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
| (...skipping 742 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 753 if (save_doubles()) { | 753 if (save_doubles()) { |
| 754 __ MultiPopFPU(kCallerSavedFPU); | 754 __ MultiPopFPU(kCallerSavedFPU); |
| 755 } | 755 } |
| 756 | 756 |
| 757 __ MultiPop(kJSCallerSaved | ra.bit()); | 757 __ MultiPop(kJSCallerSaved | ra.bit()); |
| 758 __ Ret(); | 758 __ Ret(); |
| 759 } | 759 } |
| 760 | 760 |
| 761 | 761 |
| 762 void MathPowStub::Generate(MacroAssembler* masm) { | 762 void MathPowStub::Generate(MacroAssembler* masm) { |
| 763 const Register base = a1; | |
| 764 const Register exponent = MathPowTaggedDescriptor::exponent(); | 763 const Register exponent = MathPowTaggedDescriptor::exponent(); |
| 765 DCHECK(exponent.is(a2)); | 764 DCHECK(exponent.is(a2)); |
| 766 const Register heapnumbermap = t1; | |
| 767 const Register heapnumber = v0; | |
| 768 const DoubleRegister double_base = f2; | 765 const DoubleRegister double_base = f2; |
| 769 const DoubleRegister double_exponent = f4; | 766 const DoubleRegister double_exponent = f4; |
| 770 const DoubleRegister double_result = f0; | 767 const DoubleRegister double_result = f0; |
| 771 const DoubleRegister double_scratch = f6; | 768 const DoubleRegister double_scratch = f6; |
| 772 const FPURegister single_scratch = f8; | 769 const FPURegister single_scratch = f8; |
| 773 const Register scratch = t5; | 770 const Register scratch = t5; |
| 774 const Register scratch2 = t3; | 771 const Register scratch2 = t3; |
| 775 | 772 |
| 776 Label call_runtime, done, int_exponent; | 773 Label call_runtime, done, int_exponent; |
| 777 if (exponent_type() == ON_STACK) { | 774 if (exponent_type() == TAGGED) { |
| 778 Label base_is_smi, unpack_exponent; | |
| 779 // The exponent and base are supplied as arguments on the stack. | |
| 780 // This can only happen if the stub is called from non-optimized code. | |
| 781 // Load input parameters from stack to double registers. | |
| 782 __ lw(base, MemOperand(sp, 1 * kPointerSize)); | |
| 783 __ lw(exponent, MemOperand(sp, 0 * kPointerSize)); | |
| 784 | |
| 785 __ LoadRoot(heapnumbermap, Heap::kHeapNumberMapRootIndex); | |
| 786 | |
| 787 __ UntagAndJumpIfSmi(scratch, base, &base_is_smi); | |
| 788 __ lw(scratch, FieldMemOperand(base, JSObject::kMapOffset)); | |
| 789 __ Branch(&call_runtime, ne, scratch, Operand(heapnumbermap)); | |
| 790 | |
| 791 __ ldc1(double_base, FieldMemOperand(base, HeapNumber::kValueOffset)); | |
| 792 __ jmp(&unpack_exponent); | |
| 793 | |
| 794 __ bind(&base_is_smi); | |
| 795 __ mtc1(scratch, single_scratch); | |
| 796 __ cvt_d_w(double_base, single_scratch); | |
| 797 __ bind(&unpack_exponent); | |
| 798 | |
| 799 __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent); | |
| 800 | |
| 801 __ lw(scratch, FieldMemOperand(exponent, JSObject::kMapOffset)); | |
| 802 __ Branch(&call_runtime, ne, scratch, Operand(heapnumbermap)); | |
| 803 __ ldc1(double_exponent, | |
| 804 FieldMemOperand(exponent, HeapNumber::kValueOffset)); | |
| 805 } else if (exponent_type() == TAGGED) { | |
| 806 // Base is already in double_base. | 775 // Base is already in double_base. |
| 807 __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent); | 776 __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent); |
| 808 | 777 |
| 809 __ ldc1(double_exponent, | 778 __ ldc1(double_exponent, |
| 810 FieldMemOperand(exponent, HeapNumber::kValueOffset)); | 779 FieldMemOperand(exponent, HeapNumber::kValueOffset)); |
| 811 } | 780 } |
| 812 | 781 |
| 813 if (exponent_type() != INTEGER) { | 782 if (exponent_type() != INTEGER) { |
| 814 Label int_exponent_convert; | 783 Label int_exponent_convert; |
| 815 // Detect integer exponents stored as double. | 784 // Detect integer exponents stored as double. |
| 816 __ EmitFPUTruncate(kRoundToMinusInf, | 785 __ EmitFPUTruncate(kRoundToMinusInf, |
| 817 scratch, | 786 scratch, |
| 818 double_exponent, | 787 double_exponent, |
| 819 at, | 788 at, |
| 820 double_scratch, | 789 double_scratch, |
| 821 scratch2, | 790 scratch2, |
| 822 kCheckForInexactConversion); | 791 kCheckForInexactConversion); |
| 823 // scratch2 == 0 means there was no conversion error. | 792 // scratch2 == 0 means there was no conversion error. |
| 824 __ Branch(&int_exponent_convert, eq, scratch2, Operand(zero_reg)); | 793 __ Branch(&int_exponent_convert, eq, scratch2, Operand(zero_reg)); |
| 825 | 794 |
| 826 if (exponent_type() == ON_STACK) { | |
| 827 // Detect square root case. Crankshaft detects constant +/-0.5 at | |
| 828 // compile time and uses DoMathPowHalf instead. We then skip this check | |
| 829 // for non-constant cases of +/-0.5 as these hardly occur. | |
| 830 Label not_plus_half; | |
| 831 // Test for 0.5. | |
| 832 __ Move(double_scratch, 0.5); | |
| 833 __ BranchF(USE_DELAY_SLOT, | |
| 834 ¬_plus_half, | |
| 835 NULL, | |
| 836 ne, | |
| 837 double_exponent, | |
| 838 double_scratch); | |
| 839 // double_scratch can be overwritten in the delay slot. | |
| 840 // Calculates square root of base. Check for the special case of | |
| 841 // Math.pow(-Infinity, 0.5) == Infinity (ECMA spec, 15.8.2.13). | |
| 842 __ Move(double_scratch, static_cast<double>(-V8_INFINITY)); | |
| 843 __ BranchF(USE_DELAY_SLOT, &done, NULL, eq, double_base, double_scratch); | |
| 844 __ neg_d(double_result, double_scratch); | |
| 845 | |
| 846 // Add +0 to convert -0 to +0. | |
| 847 __ add_d(double_scratch, double_base, kDoubleRegZero); | |
| 848 __ sqrt_d(double_result, double_scratch); | |
| 849 __ jmp(&done); | |
| 850 | |
| 851 __ bind(¬_plus_half); | |
| 852 __ Move(double_scratch, -0.5); | |
| 853 __ BranchF(USE_DELAY_SLOT, | |
| 854 &call_runtime, | |
| 855 NULL, | |
| 856 ne, | |
| 857 double_exponent, | |
| 858 double_scratch); | |
| 859 // double_scratch can be overwritten in the delay slot. | |
| 860 // Calculates square root of base. Check for the special case of | |
| 861 // Math.pow(-Infinity, -0.5) == 0 (ECMA spec, 15.8.2.13). | |
| 862 __ Move(double_scratch, static_cast<double>(-V8_INFINITY)); | |
| 863 __ BranchF(USE_DELAY_SLOT, &done, NULL, eq, double_base, double_scratch); | |
| 864 __ Move(double_result, kDoubleRegZero); | |
| 865 | |
| 866 // Add +0 to convert -0 to +0. | |
| 867 __ add_d(double_scratch, double_base, kDoubleRegZero); | |
| 868 __ Move(double_result, 1.); | |
| 869 __ sqrt_d(double_scratch, double_scratch); | |
| 870 __ div_d(double_result, double_result, double_scratch); | |
| 871 __ jmp(&done); | |
| 872 } | |
| 873 | |
| 874 __ push(ra); | 795 __ push(ra); |
| 875 { | 796 { |
| 876 AllowExternalCallThatCantCauseGC scope(masm); | 797 AllowExternalCallThatCantCauseGC scope(masm); |
| 877 __ PrepareCallCFunction(0, 2, scratch2); | 798 __ PrepareCallCFunction(0, 2, scratch2); |
| 878 __ MovToFloatParameters(double_base, double_exponent); | 799 __ MovToFloatParameters(double_base, double_exponent); |
| 879 __ CallCFunction( | 800 __ CallCFunction( |
| 880 ExternalReference::power_double_double_function(isolate()), | 801 ExternalReference::power_double_double_function(isolate()), |
| 881 0, 2); | 802 0, 2); |
| 882 } | 803 } |
| 883 __ pop(ra); | 804 __ pop(ra); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 931 // Test whether result is zero. Bail out to check for subnormal result. | 852 // Test whether result is zero. Bail out to check for subnormal result. |
| 932 // Due to subnormals, x^-y == (1/x)^y does not hold in all cases. | 853 // Due to subnormals, x^-y == (1/x)^y does not hold in all cases. |
| 933 __ BranchF(&done, NULL, ne, double_result, kDoubleRegZero); | 854 __ BranchF(&done, NULL, ne, double_result, kDoubleRegZero); |
| 934 | 855 |
| 935 // double_exponent may not contain the exponent value if the input was a | 856 // double_exponent may not contain the exponent value if the input was a |
| 936 // smi. We set it with exponent value before bailing out. | 857 // smi. We set it with exponent value before bailing out. |
| 937 __ mtc1(exponent, single_scratch); | 858 __ mtc1(exponent, single_scratch); |
| 938 __ cvt_d_w(double_exponent, single_scratch); | 859 __ cvt_d_w(double_exponent, single_scratch); |
| 939 | 860 |
| 940 // Returning or bailing out. | 861 // Returning or bailing out. |
| 941 if (exponent_type() == ON_STACK) { | 862 __ push(ra); |
| 942 // The arguments are still on the stack. | 863 { |
| 943 __ bind(&call_runtime); | 864 AllowExternalCallThatCantCauseGC scope(masm); |
| 944 __ TailCallRuntime(Runtime::kMathPowRT); | 865 __ PrepareCallCFunction(0, 2, scratch); |
| 866 __ MovToFloatParameters(double_base, double_exponent); |
| 867 __ CallCFunction(ExternalReference::power_double_double_function(isolate()), |
| 868 0, 2); |
| 869 } |
| 870 __ pop(ra); |
| 871 __ MovFromFloatResult(double_result); |
| 945 | 872 |
| 946 // The stub is called from non-optimized code, which expects the result | 873 __ bind(&done); |
| 947 // as heap number in exponent. | 874 __ Ret(); |
| 948 __ bind(&done); | |
| 949 __ AllocateHeapNumber( | |
| 950 heapnumber, scratch, scratch2, heapnumbermap, &call_runtime); | |
| 951 __ sdc1(double_result, | |
| 952 FieldMemOperand(heapnumber, HeapNumber::kValueOffset)); | |
| 953 DCHECK(heapnumber.is(v0)); | |
| 954 __ DropAndRet(2); | |
| 955 } else { | |
| 956 __ push(ra); | |
| 957 { | |
| 958 AllowExternalCallThatCantCauseGC scope(masm); | |
| 959 __ PrepareCallCFunction(0, 2, scratch); | |
| 960 __ MovToFloatParameters(double_base, double_exponent); | |
| 961 __ CallCFunction( | |
| 962 ExternalReference::power_double_double_function(isolate()), | |
| 963 0, 2); | |
| 964 } | |
| 965 __ pop(ra); | |
| 966 __ MovFromFloatResult(double_result); | |
| 967 | |
| 968 __ bind(&done); | |
| 969 __ Ret(); | |
| 970 } | |
| 971 } | 875 } |
| 972 | 876 |
| 973 | |
| 974 bool CEntryStub::NeedsImmovableCode() { | 877 bool CEntryStub::NeedsImmovableCode() { |
| 975 return true; | 878 return true; |
| 976 } | 879 } |
| 977 | 880 |
| 978 | 881 |
| 979 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { | 882 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { |
| 980 CEntryStub::GenerateAheadOfTime(isolate); | 883 CEntryStub::GenerateAheadOfTime(isolate); |
| 981 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); | 884 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); |
| 982 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); | 885 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); |
| 983 CommonArrayConstructorStub::GenerateStubsAheadOfTime(isolate); | 886 CommonArrayConstructorStub::GenerateStubsAheadOfTime(isolate); |
| (...skipping 4532 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5516 kStackUnwindSpace, kInvalidStackOffset, | 5419 kStackUnwindSpace, kInvalidStackOffset, |
| 5517 return_value_operand, NULL); | 5420 return_value_operand, NULL); |
| 5518 } | 5421 } |
| 5519 | 5422 |
| 5520 #undef __ | 5423 #undef __ |
| 5521 | 5424 |
| 5522 } // namespace internal | 5425 } // namespace internal |
| 5523 } // namespace v8 | 5426 } // namespace v8 |
| 5524 | 5427 |
| 5525 #endif // V8_TARGET_ARCH_MIPS | 5428 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |