OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 798 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
809 __ mov(dst1, zero_reg); | 809 __ mov(dst1, zero_reg); |
810 } | 810 } |
811 __ bind(&done); | 811 __ bind(&done); |
812 } | 812 } |
813 | 813 |
814 | 814 |
815 void FloatingPointHelper::LoadNumberAsInt32Double(MacroAssembler* masm, | 815 void FloatingPointHelper::LoadNumberAsInt32Double(MacroAssembler* masm, |
816 Register object, | 816 Register object, |
817 Destination destination, | 817 Destination destination, |
818 DoubleRegister double_dst, | 818 DoubleRegister double_dst, |
| 819 DoubleRegister double_scratch, |
819 Register dst1, | 820 Register dst1, |
820 Register dst2, | 821 Register dst2, |
821 Register heap_number_map, | 822 Register heap_number_map, |
822 Register scratch1, | 823 Register scratch1, |
823 Register scratch2, | 824 Register scratch2, |
824 FPURegister single_scratch, | 825 FPURegister single_scratch, |
825 Label* not_int32) { | 826 Label* not_int32) { |
826 ASSERT(!scratch1.is(object) && !scratch2.is(object)); | 827 ASSERT(!scratch1.is(object) && !scratch2.is(object)); |
827 ASSERT(!scratch1.is(scratch2)); | 828 ASSERT(!scratch1.is(scratch2)); |
828 ASSERT(!heap_number_map.is(object) && | 829 ASSERT(!heap_number_map.is(object) && |
(...skipping 15 matching lines...) Expand all Loading... |
844 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32); | 845 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32); |
845 | 846 |
846 // Load the number. | 847 // Load the number. |
847 if (CpuFeatures::IsSupported(FPU)) { | 848 if (CpuFeatures::IsSupported(FPU)) { |
848 CpuFeatures::Scope scope(FPU); | 849 CpuFeatures::Scope scope(FPU); |
849 // Load the double value. | 850 // Load the double value. |
850 __ ldc1(double_dst, FieldMemOperand(object, HeapNumber::kValueOffset)); | 851 __ ldc1(double_dst, FieldMemOperand(object, HeapNumber::kValueOffset)); |
851 | 852 |
852 Register except_flag = scratch2; | 853 Register except_flag = scratch2; |
853 __ EmitFPUTruncate(kRoundToZero, | 854 __ EmitFPUTruncate(kRoundToZero, |
854 single_scratch, | 855 scratch1, |
855 double_dst, | 856 double_dst, |
856 scratch1, | 857 at, |
| 858 double_scratch, |
857 except_flag, | 859 except_flag, |
858 kCheckForInexactConversion); | 860 kCheckForInexactConversion); |
859 | 861 |
860 // Jump to not_int32 if the operation did not succeed. | 862 // Jump to not_int32 if the operation did not succeed. |
861 __ Branch(not_int32, ne, except_flag, Operand(zero_reg)); | 863 __ Branch(not_int32, ne, except_flag, Operand(zero_reg)); |
862 | 864 |
863 if (destination == kCoreRegisters) { | 865 if (destination == kCoreRegisters) { |
864 __ Move(dst1, dst2, double_dst); | 866 __ Move(dst1, dst2, double_dst); |
865 } | 867 } |
866 | 868 |
(...skipping 21 matching lines...) Expand all Loading... |
888 } | 890 } |
889 | 891 |
890 | 892 |
891 void FloatingPointHelper::LoadNumberAsInt32(MacroAssembler* masm, | 893 void FloatingPointHelper::LoadNumberAsInt32(MacroAssembler* masm, |
892 Register object, | 894 Register object, |
893 Register dst, | 895 Register dst, |
894 Register heap_number_map, | 896 Register heap_number_map, |
895 Register scratch1, | 897 Register scratch1, |
896 Register scratch2, | 898 Register scratch2, |
897 Register scratch3, | 899 Register scratch3, |
898 DoubleRegister double_scratch, | 900 DoubleRegister double_scratch0, |
| 901 DoubleRegister double_scratch1, |
899 Label* not_int32) { | 902 Label* not_int32) { |
900 ASSERT(!dst.is(object)); | 903 ASSERT(!dst.is(object)); |
901 ASSERT(!scratch1.is(object) && !scratch2.is(object) && !scratch3.is(object)); | 904 ASSERT(!scratch1.is(object) && !scratch2.is(object) && !scratch3.is(object)); |
902 ASSERT(!scratch1.is(scratch2) && | 905 ASSERT(!scratch1.is(scratch2) && |
903 !scratch1.is(scratch3) && | 906 !scratch1.is(scratch3) && |
904 !scratch2.is(scratch3)); | 907 !scratch2.is(scratch3)); |
905 | 908 |
906 Label done, maybe_undefined; | 909 Label done, maybe_undefined; |
907 | 910 |
908 __ UntagAndJumpIfSmi(dst, object, &done); | 911 __ UntagAndJumpIfSmi(dst, object, &done); |
909 | 912 |
910 __ AssertRootValue(heap_number_map, | 913 __ AssertRootValue(heap_number_map, |
911 Heap::kHeapNumberMapRootIndex, | 914 Heap::kHeapNumberMapRootIndex, |
912 "HeapNumberMap register clobbered."); | 915 "HeapNumberMap register clobbered."); |
913 | 916 |
914 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, &maybe_undefined); | 917 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, &maybe_undefined); |
915 | 918 |
916 // Object is a heap number. | 919 // Object is a heap number. |
917 // Convert the floating point value to a 32-bit integer. | 920 // Convert the floating point value to a 32-bit integer. |
918 if (CpuFeatures::IsSupported(FPU)) { | 921 if (CpuFeatures::IsSupported(FPU)) { |
919 CpuFeatures::Scope scope(FPU); | 922 CpuFeatures::Scope scope(FPU); |
920 // Load the double value. | 923 // Load the double value. |
921 __ ldc1(double_scratch, FieldMemOperand(object, HeapNumber::kValueOffset)); | 924 __ ldc1(double_scratch0, FieldMemOperand(object, HeapNumber::kValueOffset)); |
922 | 925 |
923 FPURegister single_scratch = double_scratch.low(); | |
924 Register except_flag = scratch2; | 926 Register except_flag = scratch2; |
925 __ EmitFPUTruncate(kRoundToZero, | 927 __ EmitFPUTruncate(kRoundToZero, |
926 single_scratch, | 928 dst, |
927 double_scratch, | 929 double_scratch0, |
928 scratch1, | 930 scratch1, |
| 931 double_scratch1, |
929 except_flag, | 932 except_flag, |
930 kCheckForInexactConversion); | 933 kCheckForInexactConversion); |
931 | 934 |
932 // Jump to not_int32 if the operation did not succeed. | 935 // Jump to not_int32 if the operation did not succeed. |
933 __ Branch(not_int32, ne, except_flag, Operand(zero_reg)); | 936 __ Branch(not_int32, ne, except_flag, Operand(zero_reg)); |
934 // Get the result in the destination register. | |
935 __ mfc1(dst, single_scratch); | |
936 | |
937 } else { | 937 } else { |
938 // Load the double value in the destination registers. | 938 // Load the double value in the destination registers. |
939 __ lw(scratch2, FieldMemOperand(object, HeapNumber::kExponentOffset)); | 939 __ lw(scratch2, FieldMemOperand(object, HeapNumber::kExponentOffset)); |
940 __ lw(scratch1, FieldMemOperand(object, HeapNumber::kMantissaOffset)); | 940 __ lw(scratch1, FieldMemOperand(object, HeapNumber::kMantissaOffset)); |
941 | 941 |
942 // Check for 0 and -0. | 942 // Check for 0 and -0. |
943 __ And(dst, scratch1, Operand(~HeapNumber::kSignMask)); | 943 __ And(dst, scratch1, Operand(~HeapNumber::kSignMask)); |
944 __ Or(dst, scratch2, Operand(dst)); | 944 __ Or(dst, scratch2, Operand(dst)); |
945 __ Branch(&done, eq, dst, Operand(zero_reg)); | 945 __ Branch(&done, eq, dst, Operand(zero_reg)); |
946 | 946 |
(...skipping 2001 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2948 // and left) are preserved for the runtime call. | 2948 // and left) are preserved for the runtime call. |
2949 FloatingPointHelper::Destination destination = | 2949 FloatingPointHelper::Destination destination = |
2950 (CpuFeatures::IsSupported(FPU) && op_ != Token::MOD) | 2950 (CpuFeatures::IsSupported(FPU) && op_ != Token::MOD) |
2951 ? FloatingPointHelper::kFPURegisters | 2951 ? FloatingPointHelper::kFPURegisters |
2952 : FloatingPointHelper::kCoreRegisters; | 2952 : FloatingPointHelper::kCoreRegisters; |
2953 | 2953 |
2954 FloatingPointHelper::LoadNumberAsInt32Double(masm, | 2954 FloatingPointHelper::LoadNumberAsInt32Double(masm, |
2955 right, | 2955 right, |
2956 destination, | 2956 destination, |
2957 f14, | 2957 f14, |
| 2958 f16, |
2958 a2, | 2959 a2, |
2959 a3, | 2960 a3, |
2960 heap_number_map, | 2961 heap_number_map, |
2961 scratch1, | 2962 scratch1, |
2962 scratch2, | 2963 scratch2, |
2963 f2, | 2964 f2, |
2964 &transition); | 2965 &transition); |
2965 FloatingPointHelper::LoadNumberAsInt32Double(masm, | 2966 FloatingPointHelper::LoadNumberAsInt32Double(masm, |
2966 left, | 2967 left, |
2967 destination, | 2968 destination, |
2968 f12, | 2969 f12, |
| 2970 f16, |
2969 t0, | 2971 t0, |
2970 t1, | 2972 t1, |
2971 heap_number_map, | 2973 heap_number_map, |
2972 scratch1, | 2974 scratch1, |
2973 scratch2, | 2975 scratch2, |
2974 f2, | 2976 f2, |
2975 &transition); | 2977 &transition); |
2976 | 2978 |
2977 if (destination == FloatingPointHelper::kFPURegisters) { | 2979 if (destination == FloatingPointHelper::kFPURegisters) { |
2978 CpuFeatures::Scope scope(FPU); | 2980 CpuFeatures::Scope scope(FPU); |
(...skipping 16 matching lines...) Expand all Loading... |
2995 } | 2997 } |
2996 | 2998 |
2997 if (op_ != Token::DIV) { | 2999 if (op_ != Token::DIV) { |
2998 // These operations produce an integer result. | 3000 // These operations produce an integer result. |
2999 // Try to return a smi if we can. | 3001 // Try to return a smi if we can. |
3000 // Otherwise return a heap number if allowed, or jump to type | 3002 // Otherwise return a heap number if allowed, or jump to type |
3001 // transition. | 3003 // transition. |
3002 | 3004 |
3003 Register except_flag = scratch2; | 3005 Register except_flag = scratch2; |
3004 __ EmitFPUTruncate(kRoundToZero, | 3006 __ EmitFPUTruncate(kRoundToZero, |
3005 single_scratch, | 3007 scratch1, |
3006 f10, | 3008 f10, |
3007 scratch1, | 3009 at, |
| 3010 f16, |
3008 except_flag); | 3011 except_flag); |
3009 | 3012 |
3010 if (result_type_ <= BinaryOpIC::INT32) { | 3013 if (result_type_ <= BinaryOpIC::INT32) { |
3011 // If except_flag != 0, result does not fit in a 32-bit integer. | 3014 // If except_flag != 0, result does not fit in a 32-bit integer. |
3012 __ Branch(&transition, ne, except_flag, Operand(zero_reg)); | 3015 __ Branch(&transition, ne, except_flag, Operand(zero_reg)); |
3013 } | 3016 } |
3014 | 3017 |
3015 // Check if the result fits in a smi. | 3018 // Check if the result fits in a smi. |
3016 __ mfc1(scratch1, single_scratch); | |
3017 __ Addu(scratch2, scratch1, Operand(0x40000000)); | 3019 __ Addu(scratch2, scratch1, Operand(0x40000000)); |
3018 // If not try to return a heap number. | 3020 // If not try to return a heap number. |
3019 __ Branch(&return_heap_number, lt, scratch2, Operand(zero_reg)); | 3021 __ Branch(&return_heap_number, lt, scratch2, Operand(zero_reg)); |
3020 // Check for minus zero. Return heap number for minus zero. | 3022 // Check for minus zero. Return heap number for minus zero. |
3021 Label not_zero; | 3023 Label not_zero; |
3022 __ Branch(¬_zero, ne, scratch1, Operand(zero_reg)); | 3024 __ Branch(¬_zero, ne, scratch1, Operand(zero_reg)); |
3023 __ mfc1(scratch2, f11); | 3025 __ mfc1(scratch2, f11); |
3024 __ And(scratch2, scratch2, HeapNumber::kSignMask); | 3026 __ And(scratch2, scratch2, HeapNumber::kSignMask); |
3025 __ Branch(&return_heap_number, ne, scratch2, Operand(zero_reg)); | 3027 __ Branch(&return_heap_number, ne, scratch2, Operand(zero_reg)); |
3026 __ bind(¬_zero); | 3028 __ bind(¬_zero); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3101 // registers a0 and a1 (right and left) are preserved for the runtime | 3103 // registers a0 and a1 (right and left) are preserved for the runtime |
3102 // call. | 3104 // call. |
3103 FloatingPointHelper::LoadNumberAsInt32(masm, | 3105 FloatingPointHelper::LoadNumberAsInt32(masm, |
3104 left, | 3106 left, |
3105 a3, | 3107 a3, |
3106 heap_number_map, | 3108 heap_number_map, |
3107 scratch1, | 3109 scratch1, |
3108 scratch2, | 3110 scratch2, |
3109 scratch3, | 3111 scratch3, |
3110 f0, | 3112 f0, |
| 3113 f2, |
3111 &transition); | 3114 &transition); |
3112 FloatingPointHelper::LoadNumberAsInt32(masm, | 3115 FloatingPointHelper::LoadNumberAsInt32(masm, |
3113 right, | 3116 right, |
3114 a2, | 3117 a2, |
3115 heap_number_map, | 3118 heap_number_map, |
3116 scratch1, | 3119 scratch1, |
3117 scratch2, | 3120 scratch2, |
3118 scratch3, | 3121 scratch3, |
3119 f0, | 3122 f0, |
| 3123 f2, |
3120 &transition); | 3124 &transition); |
3121 | 3125 |
3122 // The ECMA-262 standard specifies that, for shift operations, only the | 3126 // The ECMA-262 standard specifies that, for shift operations, only the |
3123 // 5 least significant bits of the shift value should be used. | 3127 // 5 least significant bits of the shift value should be used. |
3124 switch (op_) { | 3128 switch (op_) { |
3125 case Token::BIT_OR: | 3129 case Token::BIT_OR: |
3126 __ Or(a2, a3, Operand(a2)); | 3130 __ Or(a2, a3, Operand(a2)); |
3127 break; | 3131 break; |
3128 case Token::BIT_XOR: | 3132 case Token::BIT_XOR: |
3129 __ Xor(a2, a3, Operand(a2)); | 3133 __ Xor(a2, a3, Operand(a2)); |
(...skipping 546 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3676 __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent); | 3680 __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent); |
3677 | 3681 |
3678 __ ldc1(double_exponent, | 3682 __ ldc1(double_exponent, |
3679 FieldMemOperand(exponent, HeapNumber::kValueOffset)); | 3683 FieldMemOperand(exponent, HeapNumber::kValueOffset)); |
3680 } | 3684 } |
3681 | 3685 |
3682 if (exponent_type_ != INTEGER) { | 3686 if (exponent_type_ != INTEGER) { |
3683 Label int_exponent_convert; | 3687 Label int_exponent_convert; |
3684 // Detect integer exponents stored as double. | 3688 // Detect integer exponents stored as double. |
3685 __ EmitFPUTruncate(kRoundToMinusInf, | 3689 __ EmitFPUTruncate(kRoundToMinusInf, |
3686 single_scratch, | 3690 scratch, |
3687 double_exponent, | 3691 double_exponent, |
3688 scratch, | 3692 at, |
| 3693 double_scratch, |
3689 scratch2, | 3694 scratch2, |
3690 kCheckForInexactConversion); | 3695 kCheckForInexactConversion); |
3691 // scratch2 == 0 means there was no conversion error. | 3696 // scratch2 == 0 means there was no conversion error. |
3692 __ Branch(&int_exponent_convert, eq, scratch2, Operand(zero_reg)); | 3697 __ Branch(&int_exponent_convert, eq, scratch2, Operand(zero_reg)); |
3693 | 3698 |
3694 if (exponent_type_ == ON_STACK) { | 3699 if (exponent_type_ == ON_STACK) { |
3695 // Detect square root case. Crankshaft detects constant +/-0.5 at | 3700 // Detect square root case. Crankshaft detects constant +/-0.5 at |
3696 // compile time and uses DoMathPowHalf instead. We then skip this check | 3701 // compile time and uses DoMathPowHalf instead. We then skip this check |
3697 // for non-constant cases of +/-0.5 as these hardly occur. | 3702 // for non-constant cases of +/-0.5 as these hardly occur. |
3698 Label not_plus_half; | 3703 Label not_plus_half; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3736 __ add_d(double_scratch, double_base, kDoubleRegZero); | 3741 __ add_d(double_scratch, double_base, kDoubleRegZero); |
3737 __ Move(double_result, 1); | 3742 __ Move(double_result, 1); |
3738 __ sqrt_d(double_scratch, double_scratch); | 3743 __ sqrt_d(double_scratch, double_scratch); |
3739 __ div_d(double_result, double_result, double_scratch); | 3744 __ div_d(double_result, double_result, double_scratch); |
3740 __ jmp(&done); | 3745 __ jmp(&done); |
3741 } | 3746 } |
3742 | 3747 |
3743 __ push(ra); | 3748 __ push(ra); |
3744 { | 3749 { |
3745 AllowExternalCallThatCantCauseGC scope(masm); | 3750 AllowExternalCallThatCantCauseGC scope(masm); |
3746 __ PrepareCallCFunction(0, 2, scratch); | 3751 __ PrepareCallCFunction(0, 2, scratch2); |
3747 __ SetCallCDoubleArguments(double_base, double_exponent); | 3752 __ SetCallCDoubleArguments(double_base, double_exponent); |
3748 __ CallCFunction( | 3753 __ CallCFunction( |
3749 ExternalReference::power_double_double_function(masm->isolate()), | 3754 ExternalReference::power_double_double_function(masm->isolate()), |
3750 0, 2); | 3755 0, 2); |
3751 } | 3756 } |
3752 __ pop(ra); | 3757 __ pop(ra); |
3753 __ GetCFunctionDoubleResult(double_result); | 3758 __ GetCFunctionDoubleResult(double_result); |
3754 __ jmp(&done); | 3759 __ jmp(&done); |
3755 | 3760 |
3756 __ bind(&int_exponent_convert); | 3761 __ bind(&int_exponent_convert); |
3757 __ mfc1(scratch, single_scratch); | |
3758 } | 3762 } |
3759 | 3763 |
3760 // Calculate power with integer exponent. | 3764 // Calculate power with integer exponent. |
3761 __ bind(&int_exponent); | 3765 __ bind(&int_exponent); |
3762 | 3766 |
3763 // Get two copies of exponent in the registers scratch and exponent. | 3767 // Get two copies of exponent in the registers scratch and exponent. |
3764 if (exponent_type_ == INTEGER) { | 3768 if (exponent_type_ == INTEGER) { |
3765 __ mov(scratch, exponent); | 3769 __ mov(scratch, exponent); |
3766 } else { | 3770 } else { |
3767 // Exponent has previously been stored into scratch as untagged integer. | 3771 // Exponent has previously been stored into scratch as untagged integer. |
(...skipping 4016 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7784 __ Pop(ra, t1, a1); | 7788 __ Pop(ra, t1, a1); |
7785 __ Ret(); | 7789 __ Ret(); |
7786 } | 7790 } |
7787 | 7791 |
7788 | 7792 |
7789 #undef __ | 7793 #undef __ |
7790 | 7794 |
7791 } } // namespace v8::internal | 7795 } } // namespace v8::internal |
7792 | 7796 |
7793 #endif // V8_TARGET_ARCH_MIPS | 7797 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |