| 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 808 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 819 __ mov(dst1, Operand::Zero()); | 819 __ mov(dst1, Operand::Zero()); |
| 820 } | 820 } |
| 821 __ bind(&done); | 821 __ bind(&done); |
| 822 } | 822 } |
| 823 | 823 |
| 824 | 824 |
| 825 void FloatingPointHelper::LoadNumberAsInt32Double(MacroAssembler* masm, | 825 void FloatingPointHelper::LoadNumberAsInt32Double(MacroAssembler* masm, |
| 826 Register object, | 826 Register object, |
| 827 Destination destination, | 827 Destination destination, |
| 828 DwVfpRegister double_dst, | 828 DwVfpRegister double_dst, |
| 829 DwVfpRegister double_scratch, |
| 829 Register dst1, | 830 Register dst1, |
| 830 Register dst2, | 831 Register dst2, |
| 831 Register heap_number_map, | 832 Register heap_number_map, |
| 832 Register scratch1, | 833 Register scratch1, |
| 833 Register scratch2, | 834 Register scratch2, |
| 834 SwVfpRegister single_scratch, | 835 SwVfpRegister single_scratch, |
| 835 Label* not_int32) { | 836 Label* not_int32) { |
| 836 ASSERT(!scratch1.is(object) && !scratch2.is(object)); | 837 ASSERT(!scratch1.is(object) && !scratch2.is(object)); |
| 837 ASSERT(!scratch1.is(scratch2)); | 838 ASSERT(!scratch1.is(scratch2)); |
| 838 ASSERT(!heap_number_map.is(object) && | 839 ASSERT(!heap_number_map.is(object) && |
| (...skipping 17 matching lines...) Expand all Loading... |
| 856 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32); | 857 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32); |
| 857 | 858 |
| 858 // Load the number. | 859 // Load the number. |
| 859 if (CpuFeatures::IsSupported(VFP2)) { | 860 if (CpuFeatures::IsSupported(VFP2)) { |
| 860 CpuFeatures::Scope scope(VFP2); | 861 CpuFeatures::Scope scope(VFP2); |
| 861 // Load the double value. | 862 // Load the double value. |
| 862 __ sub(scratch1, object, Operand(kHeapObjectTag)); | 863 __ sub(scratch1, object, Operand(kHeapObjectTag)); |
| 863 __ vldr(double_dst, scratch1, HeapNumber::kValueOffset); | 864 __ vldr(double_dst, scratch1, HeapNumber::kValueOffset); |
| 864 | 865 |
| 865 __ EmitVFPTruncate(kRoundToZero, | 866 __ EmitVFPTruncate(kRoundToZero, |
| 866 single_scratch, | 867 scratch1, |
| 867 double_dst, | 868 double_dst, |
| 868 scratch1, | |
| 869 scratch2, | 869 scratch2, |
| 870 double_scratch, |
| 870 kCheckForInexactConversion); | 871 kCheckForInexactConversion); |
| 871 | 872 |
| 872 // Jump to not_int32 if the operation did not succeed. | 873 // Jump to not_int32 if the operation did not succeed. |
| 873 __ b(ne, not_int32); | 874 __ b(ne, not_int32); |
| 874 | 875 |
| 875 if (destination == kCoreRegisters) { | 876 if (destination == kCoreRegisters) { |
| 876 __ vmov(dst1, dst2, double_dst); | 877 __ vmov(dst1, dst2, double_dst); |
| 877 } | 878 } |
| 878 | 879 |
| 879 } else { | 880 } else { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 899 } | 900 } |
| 900 | 901 |
| 901 | 902 |
| 902 void FloatingPointHelper::LoadNumberAsInt32(MacroAssembler* masm, | 903 void FloatingPointHelper::LoadNumberAsInt32(MacroAssembler* masm, |
| 903 Register object, | 904 Register object, |
| 904 Register dst, | 905 Register dst, |
| 905 Register heap_number_map, | 906 Register heap_number_map, |
| 906 Register scratch1, | 907 Register scratch1, |
| 907 Register scratch2, | 908 Register scratch2, |
| 908 Register scratch3, | 909 Register scratch3, |
| 909 DwVfpRegister double_scratch, | 910 DwVfpRegister double_scratch0, |
| 911 DwVfpRegister double_scratch1, |
| 910 Label* not_int32) { | 912 Label* not_int32) { |
| 911 ASSERT(!dst.is(object)); | 913 ASSERT(!dst.is(object)); |
| 912 ASSERT(!scratch1.is(object) && !scratch2.is(object) && !scratch3.is(object)); | 914 ASSERT(!scratch1.is(object) && !scratch2.is(object) && !scratch3.is(object)); |
| 913 ASSERT(!scratch1.is(scratch2) && | 915 ASSERT(!scratch1.is(scratch2) && |
| 914 !scratch1.is(scratch3) && | 916 !scratch1.is(scratch3) && |
| 915 !scratch2.is(scratch3)); | 917 !scratch2.is(scratch3)); |
| 916 | 918 |
| 917 Label done; | 919 Label done; |
| 918 | 920 |
| 919 __ UntagAndJumpIfSmi(dst, object, &done); | 921 __ UntagAndJumpIfSmi(dst, object, &done); |
| 920 | 922 |
| 921 if (FLAG_debug_code) { | 923 if (FLAG_debug_code) { |
| 922 __ AbortIfNotRootValue(heap_number_map, | 924 __ AbortIfNotRootValue(heap_number_map, |
| 923 Heap::kHeapNumberMapRootIndex, | 925 Heap::kHeapNumberMapRootIndex, |
| 924 "HeapNumberMap register clobbered."); | 926 "HeapNumberMap register clobbered."); |
| 925 } | 927 } |
| 926 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32); | 928 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32); |
| 927 | 929 |
| 928 // Object is a heap number. | 930 // Object is a heap number. |
| 929 // Convert the floating point value to a 32-bit integer. | 931 // Convert the floating point value to a 32-bit integer. |
| 930 if (CpuFeatures::IsSupported(VFP2)) { | 932 if (CpuFeatures::IsSupported(VFP2)) { |
| 931 CpuFeatures::Scope scope(VFP2); | 933 CpuFeatures::Scope scope(VFP2); |
| 932 SwVfpRegister single_scratch = double_scratch.low(); | 934 |
| 933 // Load the double value. | 935 // Load the double value. |
| 934 __ sub(scratch1, object, Operand(kHeapObjectTag)); | 936 __ sub(scratch1, object, Operand(kHeapObjectTag)); |
| 935 __ vldr(double_scratch, scratch1, HeapNumber::kValueOffset); | 937 __ vldr(double_scratch0, scratch1, HeapNumber::kValueOffset); |
| 936 | 938 |
| 937 __ EmitVFPTruncate(kRoundToZero, | 939 __ EmitVFPTruncate(kRoundToZero, |
| 938 single_scratch, | 940 dst, |
| 939 double_scratch, | 941 double_scratch0, |
| 940 scratch1, | 942 scratch1, |
| 941 scratch2, | 943 double_scratch1, |
| 942 kCheckForInexactConversion); | 944 kCheckForInexactConversion); |
| 943 | 945 |
| 944 // Jump to not_int32 if the operation did not succeed. | 946 // Jump to not_int32 if the operation did not succeed. |
| 945 __ b(ne, not_int32); | 947 __ b(ne, not_int32); |
| 946 // Get the result in the destination register. | |
| 947 __ vmov(dst, single_scratch); | |
| 948 | |
| 949 } else { | 948 } else { |
| 950 // Load the double value in the destination registers. | 949 // Load the double value in the destination registers. |
| 951 __ ldr(scratch1, FieldMemOperand(object, HeapNumber::kExponentOffset)); | 950 __ ldr(scratch1, FieldMemOperand(object, HeapNumber::kExponentOffset)); |
| 952 __ ldr(scratch2, FieldMemOperand(object, HeapNumber::kMantissaOffset)); | 951 __ ldr(scratch2, FieldMemOperand(object, HeapNumber::kMantissaOffset)); |
| 953 | 952 |
| 954 // Check for 0 and -0. | 953 // Check for 0 and -0. |
| 955 __ bic(dst, scratch1, Operand(HeapNumber::kSignMask)); | 954 __ bic(dst, scratch1, Operand(HeapNumber::kSignMask)); |
| 956 __ orr(dst, scratch2, Operand(dst)); | 955 __ orr(dst, scratch2, Operand(dst)); |
| 957 __ cmp(dst, Operand::Zero()); | 956 __ cmp(dst, Operand::Zero()); |
| 958 __ b(eq, &done); | 957 __ b(eq, &done); |
| (...skipping 1884 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2843 | 2842 |
| 2844 | 2843 |
| 2845 void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { | 2844 void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { |
| 2846 ASSERT(operands_type_ == BinaryOpIC::INT32); | 2845 ASSERT(operands_type_ == BinaryOpIC::INT32); |
| 2847 | 2846 |
| 2848 Register left = r1; | 2847 Register left = r1; |
| 2849 Register right = r0; | 2848 Register right = r0; |
| 2850 Register scratch1 = r7; | 2849 Register scratch1 = r7; |
| 2851 Register scratch2 = r9; | 2850 Register scratch2 = r9; |
| 2852 DwVfpRegister double_scratch = d0; | 2851 DwVfpRegister double_scratch = d0; |
| 2853 SwVfpRegister single_scratch = s3; | |
| 2854 | 2852 |
| 2855 Register heap_number_result = no_reg; | 2853 Register heap_number_result = no_reg; |
| 2856 Register heap_number_map = r6; | 2854 Register heap_number_map = r6; |
| 2857 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); | 2855 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); |
| 2858 | 2856 |
| 2859 Label call_runtime; | 2857 Label call_runtime; |
| 2860 // Labels for type transition, used for wrong input or output types. | 2858 // Labels for type transition, used for wrong input or output types. |
| 2861 // Both label are currently actually bound to the same position. We use two | 2859 // Both label are currently actually bound to the same position. We use two |
| 2862 // different label to differentiate the cause leading to type transition. | 2860 // different label to differentiate the cause leading to type transition. |
| 2863 Label transition; | 2861 Label transition; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2881 // and left) are preserved for the runtime call. | 2879 // and left) are preserved for the runtime call. |
| 2882 FloatingPointHelper::Destination destination = | 2880 FloatingPointHelper::Destination destination = |
| 2883 (CpuFeatures::IsSupported(VFP2) && op_ != Token::MOD) | 2881 (CpuFeatures::IsSupported(VFP2) && op_ != Token::MOD) |
| 2884 ? FloatingPointHelper::kVFPRegisters | 2882 ? FloatingPointHelper::kVFPRegisters |
| 2885 : FloatingPointHelper::kCoreRegisters; | 2883 : FloatingPointHelper::kCoreRegisters; |
| 2886 | 2884 |
| 2887 FloatingPointHelper::LoadNumberAsInt32Double(masm, | 2885 FloatingPointHelper::LoadNumberAsInt32Double(masm, |
| 2888 right, | 2886 right, |
| 2889 destination, | 2887 destination, |
| 2890 d7, | 2888 d7, |
| 2889 d8, |
| 2891 r2, | 2890 r2, |
| 2892 r3, | 2891 r3, |
| 2893 heap_number_map, | 2892 heap_number_map, |
| 2894 scratch1, | 2893 scratch1, |
| 2895 scratch2, | 2894 scratch2, |
| 2896 s0, | 2895 s0, |
| 2897 &transition); | 2896 &transition); |
| 2898 FloatingPointHelper::LoadNumberAsInt32Double(masm, | 2897 FloatingPointHelper::LoadNumberAsInt32Double(masm, |
| 2899 left, | 2898 left, |
| 2900 destination, | 2899 destination, |
| 2901 d6, | 2900 d6, |
| 2901 d8, |
| 2902 r4, | 2902 r4, |
| 2903 r5, | 2903 r5, |
| 2904 heap_number_map, | 2904 heap_number_map, |
| 2905 scratch1, | 2905 scratch1, |
| 2906 scratch2, | 2906 scratch2, |
| 2907 s0, | 2907 s0, |
| 2908 &transition); | 2908 &transition); |
| 2909 | 2909 |
| 2910 if (destination == FloatingPointHelper::kVFPRegisters) { | 2910 if (destination == FloatingPointHelper::kVFPRegisters) { |
| 2911 CpuFeatures::Scope scope(VFP2); | 2911 CpuFeatures::Scope scope(VFP2); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 2927 UNREACHABLE(); | 2927 UNREACHABLE(); |
| 2928 } | 2928 } |
| 2929 | 2929 |
| 2930 if (op_ != Token::DIV) { | 2930 if (op_ != Token::DIV) { |
| 2931 // These operations produce an integer result. | 2931 // These operations produce an integer result. |
| 2932 // Try to return a smi if we can. | 2932 // Try to return a smi if we can. |
| 2933 // Otherwise return a heap number if allowed, or jump to type | 2933 // Otherwise return a heap number if allowed, or jump to type |
| 2934 // transition. | 2934 // transition. |
| 2935 | 2935 |
| 2936 __ EmitVFPTruncate(kRoundToZero, | 2936 __ EmitVFPTruncate(kRoundToZero, |
| 2937 single_scratch, | 2937 scratch1, |
| 2938 d5, | 2938 d5, |
| 2939 scratch1, | 2939 scratch2, |
| 2940 scratch2); | 2940 d8); |
| 2941 | 2941 |
| 2942 if (result_type_ <= BinaryOpIC::INT32) { | 2942 if (result_type_ <= BinaryOpIC::INT32) { |
| 2943 // If the ne condition is set, result does | 2943 // If the ne condition is set, result does |
| 2944 // not fit in a 32-bit integer. | 2944 // not fit in a 32-bit integer. |
| 2945 __ b(ne, &transition); | 2945 __ b(ne, &transition); |
| 2946 } | 2946 } |
| 2947 | 2947 |
| 2948 // Check if the result fits in a smi. | 2948 // Check if the result fits in a smi. |
| 2949 __ vmov(scratch1, single_scratch); | |
| 2950 __ add(scratch2, scratch1, Operand(0x40000000), SetCC); | 2949 __ add(scratch2, scratch1, Operand(0x40000000), SetCC); |
| 2951 // If not try to return a heap number. | 2950 // If not try to return a heap number. |
| 2952 __ b(mi, &return_heap_number); | 2951 __ b(mi, &return_heap_number); |
| 2953 // Check for minus zero. Return heap number for minus zero. | 2952 // Check for minus zero. Return heap number for minus zero. |
| 2954 Label not_zero; | 2953 Label not_zero; |
| 2955 __ cmp(scratch1, Operand::Zero()); | 2954 __ cmp(scratch1, Operand::Zero()); |
| 2956 __ b(ne, ¬_zero); | 2955 __ b(ne, ¬_zero); |
| 2957 __ vmov(scratch2, d5.high()); | 2956 __ vmov(scratch2, d5.high()); |
| 2958 __ tst(scratch2, Operand(HeapNumber::kSignMask)); | 2957 __ tst(scratch2, Operand(HeapNumber::kSignMask)); |
| 2959 __ b(ne, &return_heap_number); | 2958 __ b(ne, &return_heap_number); |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3034 // registers r0 and r1 (right and left) are preserved for the runtime | 3033 // registers r0 and r1 (right and left) are preserved for the runtime |
| 3035 // call. | 3034 // call. |
| 3036 FloatingPointHelper::LoadNumberAsInt32(masm, | 3035 FloatingPointHelper::LoadNumberAsInt32(masm, |
| 3037 left, | 3036 left, |
| 3038 r3, | 3037 r3, |
| 3039 heap_number_map, | 3038 heap_number_map, |
| 3040 scratch1, | 3039 scratch1, |
| 3041 scratch2, | 3040 scratch2, |
| 3042 scratch3, | 3041 scratch3, |
| 3043 d0, | 3042 d0, |
| 3043 d1, |
| 3044 &transition); | 3044 &transition); |
| 3045 FloatingPointHelper::LoadNumberAsInt32(masm, | 3045 FloatingPointHelper::LoadNumberAsInt32(masm, |
| 3046 right, | 3046 right, |
| 3047 r2, | 3047 r2, |
| 3048 heap_number_map, | 3048 heap_number_map, |
| 3049 scratch1, | 3049 scratch1, |
| 3050 scratch2, | 3050 scratch2, |
| 3051 scratch3, | 3051 scratch3, |
| 3052 d0, | 3052 d0, |
| 3053 d1, |
| 3053 &transition); | 3054 &transition); |
| 3054 | 3055 |
| 3055 // The ECMA-262 standard specifies that, for shift operations, only the | 3056 // The ECMA-262 standard specifies that, for shift operations, only the |
| 3056 // 5 least significant bits of the shift value should be used. | 3057 // 5 least significant bits of the shift value should be used. |
| 3057 switch (op_) { | 3058 switch (op_) { |
| 3058 case Token::BIT_OR: | 3059 case Token::BIT_OR: |
| 3059 __ orr(r2, r3, Operand(r2)); | 3060 __ orr(r2, r3, Operand(r2)); |
| 3060 break; | 3061 break; |
| 3061 case Token::BIT_XOR: | 3062 case Token::BIT_XOR: |
| 3062 __ eor(r2, r3, Operand(r2)); | 3063 __ eor(r2, r3, Operand(r2)); |
| (...skipping 4568 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7631 | 7632 |
| 7632 __ Pop(lr, r5, r1); | 7633 __ Pop(lr, r5, r1); |
| 7633 __ Ret(); | 7634 __ Ret(); |
| 7634 } | 7635 } |
| 7635 | 7636 |
| 7636 #undef __ | 7637 #undef __ |
| 7637 | 7638 |
| 7638 } } // namespace v8::internal | 7639 } } // namespace v8::internal |
| 7639 | 7640 |
| 7640 #endif // V8_TARGET_ARCH_ARM | 7641 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |