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_ARM | 5 #if V8_TARGET_ARCH_ARM |
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 676 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
687 __ mov(r0, Operand(ExternalReference::isolate_address(isolate()))); | 687 __ mov(r0, Operand(ExternalReference::isolate_address(isolate()))); |
688 __ CallCFunction( | 688 __ CallCFunction( |
689 ExternalReference::store_buffer_overflow_function(isolate()), | 689 ExternalReference::store_buffer_overflow_function(isolate()), |
690 argument_count); | 690 argument_count); |
691 if (save_doubles()) { | 691 if (save_doubles()) { |
692 __ RestoreFPRegs(sp, scratch); | 692 __ RestoreFPRegs(sp, scratch); |
693 } | 693 } |
694 __ ldm(ia_w, sp, kCallerSaved | pc.bit()); // Also pop pc to get Ret(0). | 694 __ ldm(ia_w, sp, kCallerSaved | pc.bit()); // Also pop pc to get Ret(0). |
695 } | 695 } |
696 | 696 |
697 | |
698 void MathPowStub::Generate(MacroAssembler* masm) { | 697 void MathPowStub::Generate(MacroAssembler* masm) { |
699 const Register base = r1; | |
700 const Register exponent = MathPowTaggedDescriptor::exponent(); | 698 const Register exponent = MathPowTaggedDescriptor::exponent(); |
701 DCHECK(exponent.is(r2)); | 699 DCHECK(exponent.is(r2)); |
702 const Register heapnumbermap = r5; | |
703 const Register heapnumber = r0; | |
704 const DwVfpRegister double_base = d0; | 700 const DwVfpRegister double_base = d0; |
705 const DwVfpRegister double_exponent = d1; | 701 const DwVfpRegister double_exponent = d1; |
706 const DwVfpRegister double_result = d2; | 702 const DwVfpRegister double_result = d2; |
707 const DwVfpRegister double_scratch = d3; | 703 const DwVfpRegister double_scratch = d3; |
708 const SwVfpRegister single_scratch = s6; | 704 const SwVfpRegister single_scratch = s6; |
709 const Register scratch = r9; | 705 const Register scratch = r9; |
710 const Register scratch2 = r4; | 706 const Register scratch2 = r4; |
711 | 707 |
712 Label call_runtime, done, int_exponent; | 708 Label call_runtime, done, int_exponent; |
713 if (exponent_type() == ON_STACK) { | 709 if (exponent_type() == TAGGED) { |
714 Label base_is_smi, unpack_exponent; | |
715 // The exponent and base are supplied as arguments on the stack. | |
716 // This can only happen if the stub is called from non-optimized code. | |
717 // Load input parameters from stack to double registers. | |
718 __ ldr(base, MemOperand(sp, 1 * kPointerSize)); | |
719 __ ldr(exponent, MemOperand(sp, 0 * kPointerSize)); | |
720 | |
721 __ LoadRoot(heapnumbermap, Heap::kHeapNumberMapRootIndex); | |
722 | |
723 __ UntagAndJumpIfSmi(scratch, base, &base_is_smi); | |
724 __ ldr(scratch, FieldMemOperand(base, JSObject::kMapOffset)); | |
725 __ cmp(scratch, heapnumbermap); | |
726 __ b(ne, &call_runtime); | |
727 | |
728 __ vldr(double_base, FieldMemOperand(base, HeapNumber::kValueOffset)); | |
729 __ jmp(&unpack_exponent); | |
730 | |
731 __ bind(&base_is_smi); | |
732 __ vmov(single_scratch, scratch); | |
733 __ vcvt_f64_s32(double_base, single_scratch); | |
734 __ bind(&unpack_exponent); | |
735 | |
736 __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent); | |
737 | |
738 __ ldr(scratch, FieldMemOperand(exponent, JSObject::kMapOffset)); | |
739 __ cmp(scratch, heapnumbermap); | |
740 __ b(ne, &call_runtime); | |
741 __ vldr(double_exponent, | |
742 FieldMemOperand(exponent, HeapNumber::kValueOffset)); | |
743 } else if (exponent_type() == TAGGED) { | |
744 // Base is already in double_base. | 710 // Base is already in double_base. |
745 __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent); | 711 __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent); |
746 | 712 |
747 __ vldr(double_exponent, | 713 __ vldr(double_exponent, |
748 FieldMemOperand(exponent, HeapNumber::kValueOffset)); | 714 FieldMemOperand(exponent, HeapNumber::kValueOffset)); |
749 } | 715 } |
750 | 716 |
751 if (exponent_type() != INTEGER) { | 717 if (exponent_type() != INTEGER) { |
752 Label int_exponent_convert; | 718 Label int_exponent_convert; |
753 // Detect integer exponents stored as double. | 719 // Detect integer exponents stored as double. |
754 __ vcvt_u32_f64(single_scratch, double_exponent); | 720 __ vcvt_u32_f64(single_scratch, double_exponent); |
755 // We do not check for NaN or Infinity here because comparing numbers on | 721 // We do not check for NaN or Infinity here because comparing numbers on |
756 // ARM correctly distinguishes NaNs. We end up calling the built-in. | 722 // ARM correctly distinguishes NaNs. We end up calling the built-in. |
757 __ vcvt_f64_u32(double_scratch, single_scratch); | 723 __ vcvt_f64_u32(double_scratch, single_scratch); |
758 __ VFPCompareAndSetFlags(double_scratch, double_exponent); | 724 __ VFPCompareAndSetFlags(double_scratch, double_exponent); |
759 __ b(eq, &int_exponent_convert); | 725 __ b(eq, &int_exponent_convert); |
760 | 726 |
761 if (exponent_type() == ON_STACK) { | |
762 // Detect square root case. Crankshaft detects constant +/-0.5 at | |
763 // compile time and uses DoMathPowHalf instead. We then skip this check | |
764 // for non-constant cases of +/-0.5 as these hardly occur. | |
765 Label not_plus_half; | |
766 | |
767 // Test for 0.5. | |
768 __ vmov(double_scratch, 0.5, scratch); | |
769 __ VFPCompareAndSetFlags(double_exponent, double_scratch); | |
770 __ b(ne, ¬_plus_half); | |
771 | |
772 // Calculates square root of base. Check for the special case of | |
773 // Math.pow(-Infinity, 0.5) == Infinity (ECMA spec, 15.8.2.13). | |
774 __ vmov(double_scratch, -V8_INFINITY, scratch); | |
775 __ VFPCompareAndSetFlags(double_base, double_scratch); | |
776 __ vneg(double_result, double_scratch, eq); | |
777 __ b(eq, &done); | |
778 | |
779 // Add +0 to convert -0 to +0. | |
780 __ vadd(double_scratch, double_base, kDoubleRegZero); | |
781 __ vsqrt(double_result, double_scratch); | |
782 __ jmp(&done); | |
783 | |
784 __ bind(¬_plus_half); | |
785 __ vmov(double_scratch, -0.5, scratch); | |
786 __ VFPCompareAndSetFlags(double_exponent, double_scratch); | |
787 __ b(ne, &call_runtime); | |
788 | |
789 // Calculates square root of base. Check for the special case of | |
790 // Math.pow(-Infinity, -0.5) == 0 (ECMA spec, 15.8.2.13). | |
791 __ vmov(double_scratch, -V8_INFINITY, scratch); | |
792 __ VFPCompareAndSetFlags(double_base, double_scratch); | |
793 __ vmov(double_result, kDoubleRegZero, eq); | |
794 __ b(eq, &done); | |
795 | |
796 // Add +0 to convert -0 to +0. | |
797 __ vadd(double_scratch, double_base, kDoubleRegZero); | |
798 __ vmov(double_result, 1.0, scratch); | |
799 __ vsqrt(double_scratch, double_scratch); | |
800 __ vdiv(double_result, double_result, double_scratch); | |
801 __ jmp(&done); | |
802 } | |
803 | |
804 __ push(lr); | 727 __ push(lr); |
805 { | 728 { |
806 AllowExternalCallThatCantCauseGC scope(masm); | 729 AllowExternalCallThatCantCauseGC scope(masm); |
807 __ PrepareCallCFunction(0, 2, scratch); | 730 __ PrepareCallCFunction(0, 2, scratch); |
808 __ MovToFloatParameters(double_base, double_exponent); | 731 __ MovToFloatParameters(double_base, double_exponent); |
809 __ CallCFunction( | 732 __ CallCFunction( |
810 ExternalReference::power_double_double_function(isolate()), | 733 ExternalReference::power_double_double_function(isolate()), 0, 2); |
811 0, 2); | |
812 } | 734 } |
813 __ pop(lr); | 735 __ pop(lr); |
814 __ MovFromFloatResult(double_result); | 736 __ MovFromFloatResult(double_result); |
815 __ jmp(&done); | 737 __ jmp(&done); |
816 | 738 |
817 __ bind(&int_exponent_convert); | 739 __ bind(&int_exponent_convert); |
818 __ vcvt_u32_f64(single_scratch, double_exponent); | 740 __ vcvt_u32_f64(single_scratch, double_exponent); |
819 __ vmov(scratch, single_scratch); | 741 __ vmov(scratch, single_scratch); |
820 } | 742 } |
821 | 743 |
(...skipping 29 matching lines...) Expand all Loading... |
851 // Test whether result is zero. Bail out to check for subnormal result. | 773 // Test whether result is zero. Bail out to check for subnormal result. |
852 // Due to subnormals, x^-y == (1/x)^y does not hold in all cases. | 774 // Due to subnormals, x^-y == (1/x)^y does not hold in all cases. |
853 __ VFPCompareAndSetFlags(double_result, 0.0); | 775 __ VFPCompareAndSetFlags(double_result, 0.0); |
854 __ b(ne, &done); | 776 __ b(ne, &done); |
855 // double_exponent may not containe the exponent value if the input was a | 777 // double_exponent may not containe the exponent value if the input was a |
856 // smi. We set it with exponent value before bailing out. | 778 // smi. We set it with exponent value before bailing out. |
857 __ vmov(single_scratch, exponent); | 779 __ vmov(single_scratch, exponent); |
858 __ vcvt_f64_s32(double_exponent, single_scratch); | 780 __ vcvt_f64_s32(double_exponent, single_scratch); |
859 | 781 |
860 // Returning or bailing out. | 782 // Returning or bailing out. |
861 if (exponent_type() == ON_STACK) { | 783 __ push(lr); |
862 // The arguments are still on the stack. | 784 { |
863 __ bind(&call_runtime); | 785 AllowExternalCallThatCantCauseGC scope(masm); |
864 __ TailCallRuntime(Runtime::kMathPowRT); | 786 __ PrepareCallCFunction(0, 2, scratch); |
| 787 __ MovToFloatParameters(double_base, double_exponent); |
| 788 __ CallCFunction(ExternalReference::power_double_double_function(isolate()), |
| 789 0, 2); |
| 790 } |
| 791 __ pop(lr); |
| 792 __ MovFromFloatResult(double_result); |
865 | 793 |
866 // The stub is called from non-optimized code, which expects the result | 794 __ bind(&done); |
867 // as heap number in exponent. | 795 __ Ret(); |
868 __ bind(&done); | |
869 __ AllocateHeapNumber( | |
870 heapnumber, scratch, scratch2, heapnumbermap, &call_runtime); | |
871 __ vstr(double_result, | |
872 FieldMemOperand(heapnumber, HeapNumber::kValueOffset)); | |
873 DCHECK(heapnumber.is(r0)); | |
874 __ Ret(2); | |
875 } else { | |
876 __ push(lr); | |
877 { | |
878 AllowExternalCallThatCantCauseGC scope(masm); | |
879 __ PrepareCallCFunction(0, 2, scratch); | |
880 __ MovToFloatParameters(double_base, double_exponent); | |
881 __ CallCFunction( | |
882 ExternalReference::power_double_double_function(isolate()), | |
883 0, 2); | |
884 } | |
885 __ pop(lr); | |
886 __ MovFromFloatResult(double_result); | |
887 | |
888 __ bind(&done); | |
889 __ Ret(); | |
890 } | |
891 } | 796 } |
892 | 797 |
893 | |
894 bool CEntryStub::NeedsImmovableCode() { | 798 bool CEntryStub::NeedsImmovableCode() { |
895 return true; | 799 return true; |
896 } | 800 } |
897 | 801 |
898 | 802 |
899 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { | 803 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { |
900 CEntryStub::GenerateAheadOfTime(isolate); | 804 CEntryStub::GenerateAheadOfTime(isolate); |
901 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); | 805 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); |
902 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); | 806 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); |
903 CommonArrayConstructorStub::GenerateStubsAheadOfTime(isolate); | 807 CommonArrayConstructorStub::GenerateStubsAheadOfTime(isolate); |
(...skipping 4435 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5339 CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, | 5243 CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, |
5340 kStackUnwindSpace, NULL, return_value_operand, NULL); | 5244 kStackUnwindSpace, NULL, return_value_operand, NULL); |
5341 } | 5245 } |
5342 | 5246 |
5343 #undef __ | 5247 #undef __ |
5344 | 5248 |
5345 } // namespace internal | 5249 } // namespace internal |
5346 } // namespace v8 | 5250 } // namespace v8 |
5347 | 5251 |
5348 #endif // V8_TARGET_ARCH_ARM | 5252 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |