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