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 |