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 |