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 |