| 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 |