Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(166)

Side by Side Diff: src/arm/code-stubs-arm.cc

Issue 11413014: Fix register confusion in non-VFP3 BinaryOpStubs on ARM (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | src/arm/stub-cache-arm.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 711 matching lines...) Expand 10 before | Expand all | Expand 10 after
722 scratch2, 722 scratch2,
723 scratch3); 723 scratch3);
724 __ bind(&done); 724 __ bind(&done);
725 } 725 }
726 726
727 727
728 void FloatingPointHelper::ConvertIntToDouble(MacroAssembler* masm, 728 void FloatingPointHelper::ConvertIntToDouble(MacroAssembler* masm,
729 Register int_scratch, 729 Register int_scratch,
730 Destination destination, 730 Destination destination,
731 DwVfpRegister double_dst, 731 DwVfpRegister double_dst,
732 Register dst1, 732 Register dst_mantissa,
733 Register dst2, 733 Register dst_exponent,
734 Register scratch2, 734 Register scratch2,
735 SwVfpRegister single_scratch) { 735 SwVfpRegister single_scratch) {
736 ASSERT(!int_scratch.is(scratch2)); 736 ASSERT(!int_scratch.is(scratch2));
737 ASSERT(!int_scratch.is(dst1)); 737 ASSERT(!int_scratch.is(dst_mantissa));
738 ASSERT(!int_scratch.is(dst2)); 738 ASSERT(!int_scratch.is(dst_exponent));
739 739
740 Label done; 740 Label done;
741 741
742 if (CpuFeatures::IsSupported(VFP2)) { 742 if (CpuFeatures::IsSupported(VFP2)) {
743 CpuFeatures::Scope scope(VFP2); 743 CpuFeatures::Scope scope(VFP2);
744 __ vmov(single_scratch, int_scratch); 744 __ vmov(single_scratch, int_scratch);
745 __ vcvt_f64_s32(double_dst, single_scratch); 745 __ vcvt_f64_s32(double_dst, single_scratch);
746 if (destination == kCoreRegisters) { 746 if (destination == kCoreRegisters) {
747 __ vmov(dst1, dst2, double_dst); 747 __ vmov(dst_mantissa, dst_exponent, double_dst);
748 } 748 }
749 } else { 749 } else {
750 Label fewer_than_20_useful_bits; 750 Label fewer_than_20_useful_bits;
751 // Expected output: 751 // Expected output:
752 // | dst2 | dst1 | 752 // | dst_exponent | dst_mantissa |
753 // | s | exp | mantissa | 753 // | s | exp | mantissa |
754 754
755 // Check for zero. 755 // Check for zero.
756 __ cmp(int_scratch, Operand::Zero()); 756 __ cmp(int_scratch, Operand::Zero());
757 __ mov(dst2, int_scratch); 757 __ mov(dst_exponent, int_scratch);
758 __ mov(dst1, int_scratch); 758 __ mov(dst_mantissa, int_scratch);
759 __ b(eq, &done); 759 __ b(eq, &done);
760 760
761 // Preload the sign of the value. 761 // Preload the sign of the value.
762 __ and_(dst2, int_scratch, Operand(HeapNumber::kSignMask), SetCC); 762 __ and_(dst_exponent, int_scratch, Operand(HeapNumber::kSignMask), SetCC);
763 // Get the absolute value of the object (as an unsigned integer). 763 // Get the absolute value of the object (as an unsigned integer).
764 __ rsb(int_scratch, int_scratch, Operand::Zero(), SetCC, mi); 764 __ rsb(int_scratch, int_scratch, Operand::Zero(), SetCC, mi);
765 765
766 // Get mantissa[51:20]. 766 // Get mantissa[51:20].
767 767
768 // Get the position of the first set bit. 768 // Get the position of the first set bit.
769 __ CountLeadingZeros(dst1, int_scratch, scratch2); 769 __ CountLeadingZeros(dst_mantissa, int_scratch, scratch2);
770 __ rsb(dst1, dst1, Operand(31)); 770 __ rsb(dst_mantissa, dst_mantissa, Operand(31));
771 771
772 // Set the exponent. 772 // Set the exponent.
773 __ add(scratch2, dst1, Operand(HeapNumber::kExponentBias)); 773 __ add(scratch2, dst_mantissa, Operand(HeapNumber::kExponentBias));
774 __ Bfi(dst2, scratch2, scratch2, 774 __ Bfi(dst_exponent, scratch2, scratch2,
775 HeapNumber::kExponentShift, HeapNumber::kExponentBits); 775 HeapNumber::kExponentShift, HeapNumber::kExponentBits);
776 776
777 // Clear the first non null bit. 777 // Clear the first non null bit.
778 __ mov(scratch2, Operand(1)); 778 __ mov(scratch2, Operand(1));
779 __ bic(int_scratch, int_scratch, Operand(scratch2, LSL, dst1)); 779 __ bic(int_scratch, int_scratch, Operand(scratch2, LSL, dst_mantissa));
780 780
781 __ cmp(dst1, Operand(HeapNumber::kMantissaBitsInTopWord)); 781 __ cmp(dst_mantissa, Operand(HeapNumber::kMantissaBitsInTopWord));
782 // Get the number of bits to set in the lower part of the mantissa. 782 // Get the number of bits to set in the lower part of the mantissa.
783 __ sub(scratch2, dst1, Operand(HeapNumber::kMantissaBitsInTopWord), SetCC); 783 __ sub(scratch2, dst_mantissa, Operand(HeapNumber::kMantissaBitsInTopWord),
784 SetCC);
784 __ b(mi, &fewer_than_20_useful_bits); 785 __ b(mi, &fewer_than_20_useful_bits);
785 // Set the higher 20 bits of the mantissa. 786 // Set the higher 20 bits of the mantissa.
786 __ orr(dst2, dst2, Operand(int_scratch, LSR, scratch2)); 787 __ orr(dst_exponent, dst_exponent, Operand(int_scratch, LSR, scratch2));
787 __ rsb(scratch2, scratch2, Operand(32)); 788 __ rsb(scratch2, scratch2, Operand(32));
788 __ mov(dst1, Operand(int_scratch, LSL, scratch2)); 789 __ mov(dst_mantissa, Operand(int_scratch, LSL, scratch2));
789 __ b(&done); 790 __ b(&done);
790 791
791 __ bind(&fewer_than_20_useful_bits); 792 __ bind(&fewer_than_20_useful_bits);
792 __ rsb(scratch2, dst1, Operand(HeapNumber::kMantissaBitsInTopWord)); 793 __ rsb(scratch2, dst_mantissa, Operand(HeapNumber::kMantissaBitsInTopWord));
793 __ mov(scratch2, Operand(int_scratch, LSL, scratch2)); 794 __ mov(scratch2, Operand(int_scratch, LSL, scratch2));
794 __ orr(dst2, dst2, scratch2); 795 __ orr(dst_exponent, dst_exponent, scratch2);
795 // Set dst1 to 0. 796 // Set dst1 to 0.
796 __ mov(dst1, Operand::Zero()); 797 __ mov(dst_mantissa, Operand::Zero());
797 } 798 }
798 __ bind(&done); 799 __ bind(&done);
799 } 800 }
800 801
801 802
802 void FloatingPointHelper::LoadNumberAsInt32Double(MacroAssembler* masm, 803 void FloatingPointHelper::LoadNumberAsInt32Double(MacroAssembler* masm,
803 Register object, 804 Register object,
804 Destination destination, 805 Destination destination,
805 DwVfpRegister double_dst, 806 DwVfpRegister double_dst,
806 DwVfpRegister double_scratch, 807 DwVfpRegister double_scratch,
807 Register dst1, 808 Register dst_mantissa,
808 Register dst2, 809 Register dst_exponent,
809 Register heap_number_map, 810 Register heap_number_map,
810 Register scratch1, 811 Register scratch1,
811 Register scratch2, 812 Register scratch2,
812 SwVfpRegister single_scratch, 813 SwVfpRegister single_scratch,
813 Label* not_int32) { 814 Label* not_int32) {
814 ASSERT(!scratch1.is(object) && !scratch2.is(object)); 815 ASSERT(!scratch1.is(object) && !scratch2.is(object));
815 ASSERT(!scratch1.is(scratch2)); 816 ASSERT(!scratch1.is(scratch2));
816 ASSERT(!heap_number_map.is(object) && 817 ASSERT(!heap_number_map.is(object) &&
817 !heap_number_map.is(scratch1) && 818 !heap_number_map.is(scratch1) &&
818 !heap_number_map.is(scratch2)); 819 !heap_number_map.is(scratch2));
819 820
820 Label done, obj_is_not_smi; 821 Label done, obj_is_not_smi;
821 822
822 __ JumpIfNotSmi(object, &obj_is_not_smi); 823 __ JumpIfNotSmi(object, &obj_is_not_smi);
823 __ SmiUntag(scratch1, object); 824 __ SmiUntag(scratch1, object);
824 ConvertIntToDouble(masm, scratch1, destination, double_dst, dst1, dst2, 825 ConvertIntToDouble(masm, scratch1, destination, double_dst, dst_mantissa,
825 scratch2, single_scratch); 826 dst_exponent, scratch2, single_scratch);
826 __ b(&done); 827 __ b(&done);
827 828
828 __ bind(&obj_is_not_smi); 829 __ bind(&obj_is_not_smi);
829 __ AssertRootValue(heap_number_map, 830 __ AssertRootValue(heap_number_map,
830 Heap::kHeapNumberMapRootIndex, 831 Heap::kHeapNumberMapRootIndex,
831 "HeapNumberMap register clobbered."); 832 "HeapNumberMap register clobbered.");
832 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32); 833 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32);
833 834
834 // Load the number. 835 // Load the number.
835 if (CpuFeatures::IsSupported(VFP2)) { 836 if (CpuFeatures::IsSupported(VFP2)) {
836 CpuFeatures::Scope scope(VFP2); 837 CpuFeatures::Scope scope(VFP2);
837 // Load the double value. 838 // Load the double value.
838 __ sub(scratch1, object, Operand(kHeapObjectTag)); 839 __ sub(scratch1, object, Operand(kHeapObjectTag));
839 __ vldr(double_dst, scratch1, HeapNumber::kValueOffset); 840 __ vldr(double_dst, scratch1, HeapNumber::kValueOffset);
840 841
841 __ EmitVFPTruncate(kRoundToZero, 842 __ EmitVFPTruncate(kRoundToZero,
842 scratch1, 843 scratch1,
843 double_dst, 844 double_dst,
844 scratch2, 845 scratch2,
845 double_scratch, 846 double_scratch,
846 kCheckForInexactConversion); 847 kCheckForInexactConversion);
847 848
848 // Jump to not_int32 if the operation did not succeed. 849 // Jump to not_int32 if the operation did not succeed.
849 __ b(ne, not_int32); 850 __ b(ne, not_int32);
850 851
851 if (destination == kCoreRegisters) { 852 if (destination == kCoreRegisters) {
852 __ vmov(dst1, dst2, double_dst); 853 __ vmov(dst_mantissa, dst_exponent, double_dst);
853 } 854 }
854 855
855 } else { 856 } else {
856 ASSERT(!scratch1.is(object) && !scratch2.is(object)); 857 ASSERT(!scratch1.is(object) && !scratch2.is(object));
857 // Load the double value in the destination registers.. 858 // Load the double value in the destination registers.
858 __ Ldrd(dst1, dst2, FieldMemOperand(object, HeapNumber::kValueOffset)); 859 bool save_registers = object.is(dst_mantissa) || object.is(dst_exponent);
860 if (save_registers) {
861 // Save both output registers, because the other one probably holds
862 // an important value too.
863 __ Push(dst_exponent, dst_mantissa);
864 }
865 __ Ldrd(dst_mantissa, dst_exponent,
866 FieldMemOperand(object, HeapNumber::kValueOffset));
859 867
860 // Check for 0 and -0. 868 // Check for 0 and -0.
861 __ bic(scratch1, dst1, Operand(HeapNumber::kSignMask)); 869 Label zero;
862 __ orr(scratch1, scratch1, Operand(dst2)); 870 __ bic(scratch1, dst_exponent, Operand(HeapNumber::kSignMask));
Jakob Kummerow 2012/11/15 17:28:42 Bug fix 1: This code cleared the mantissa's sign b
871 __ orr(scratch1, scratch1, Operand(dst_mantissa));
863 __ cmp(scratch1, Operand::Zero()); 872 __ cmp(scratch1, Operand::Zero());
864 __ b(eq, &done); 873 __ b(eq, &zero);
865 874
866 // Check that the value can be exactly represented by a 32-bit integer. 875 // Check that the value can be exactly represented by a 32-bit integer.
867 // Jump to not_int32 if that's not the case. 876 // Jump to not_int32 if that's not the case.
868 DoubleIs32BitInteger(masm, dst1, dst2, scratch1, scratch2, not_int32); 877 Label restore_input_and_miss;
878 DoubleIs32BitInteger(masm, dst_exponent, dst_mantissa, scratch1, scratch2,
Jakob Kummerow 2012/11/15 17:28:42 Bug fix 2: This call passed in the exponent/mantis
879 &restore_input_and_miss);
869 880
870 // dst1 and dst2 were trashed. Reload the double value. 881 // dst_* were trashed. Reload the double value.
871 __ Ldrd(dst1, dst2, FieldMemOperand(object, HeapNumber::kValueOffset)); 882 if (save_registers) {
883 __ Pop(dst_exponent, dst_mantissa);
Jakob Kummerow 2012/11/15 17:28:42 Bug fix 3: Restore the "object" register before re
884 }
885 __ Ldrd(dst_mantissa, dst_exponent,
886 FieldMemOperand(object, HeapNumber::kValueOffset));
887 __ b(&done);
888
889 __ bind(&restore_input_and_miss);
890 if (save_registers) {
891 __ Pop(dst_exponent, dst_mantissa);
Jakob Kummerow 2012/11/15 17:28:42 Bug fix 4: Restore original inputs before calling
892 }
893 __ b(not_int32);
894
895 __ bind(&zero);
896 if (save_registers) {
897 __ Drop(2);
898 }
872 } 899 }
873 900
874 __ bind(&done); 901 __ bind(&done);
875 } 902 }
876 903
877 904
878 void FloatingPointHelper::LoadNumberAsInt32(MacroAssembler* masm, 905 void FloatingPointHelper::LoadNumberAsInt32(MacroAssembler* masm,
879 Register object, 906 Register object,
880 Register dst, 907 Register dst,
881 Register heap_number_map, 908 Register heap_number_map,
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
953 __ b(ne, not_int32); 980 __ b(ne, not_int32);
954 // |undefined| is truncated to 0. 981 // |undefined| is truncated to 0.
955 __ mov(dst, Operand(Smi::FromInt(0))); 982 __ mov(dst, Operand(Smi::FromInt(0)));
956 // Fall through. 983 // Fall through.
957 984
958 __ bind(&done); 985 __ bind(&done);
959 } 986 }
960 987
961 988
962 void FloatingPointHelper::DoubleIs32BitInteger(MacroAssembler* masm, 989 void FloatingPointHelper::DoubleIs32BitInteger(MacroAssembler* masm,
963 Register src1, 990 Register src_exponent,
964 Register src2, 991 Register src_mantissa,
965 Register dst, 992 Register dst,
966 Register scratch, 993 Register scratch,
967 Label* not_int32) { 994 Label* not_int32) {
968 // Get exponent alone in scratch. 995 // Get exponent alone in scratch.
969 __ Ubfx(scratch, 996 __ Ubfx(scratch,
970 src1, 997 src_exponent,
971 HeapNumber::kExponentShift, 998 HeapNumber::kExponentShift,
972 HeapNumber::kExponentBits); 999 HeapNumber::kExponentBits);
973 1000
974 // Substract the bias from the exponent. 1001 // Substract the bias from the exponent.
975 __ sub(scratch, scratch, Operand(HeapNumber::kExponentBias), SetCC); 1002 __ sub(scratch, scratch, Operand(HeapNumber::kExponentBias), SetCC);
976 1003
977 // src1: higher (exponent) part of the double value. 1004 // src1: higher (exponent) part of the double value.
978 // src2: lower (mantissa) part of the double value. 1005 // src2: lower (mantissa) part of the double value.
979 // scratch: unbiased exponent. 1006 // scratch: unbiased exponent.
980 1007
981 // Fast cases. Check for obvious non 32-bit integer values. 1008 // Fast cases. Check for obvious non 32-bit integer values.
982 // Negative exponent cannot yield 32-bit integers. 1009 // Negative exponent cannot yield 32-bit integers.
983 __ b(mi, not_int32); 1010 __ b(mi, not_int32);
984 // Exponent greater than 31 cannot yield 32-bit integers. 1011 // Exponent greater than 31 cannot yield 32-bit integers.
985 // Also, a positive value with an exponent equal to 31 is outside of the 1012 // Also, a positive value with an exponent equal to 31 is outside of the
986 // signed 32-bit integer range. 1013 // signed 32-bit integer range.
987 // Another way to put it is that if (exponent - signbit) > 30 then the 1014 // Another way to put it is that if (exponent - signbit) > 30 then the
988 // number cannot be represented as an int32. 1015 // number cannot be represented as an int32.
989 Register tmp = dst; 1016 Register tmp = dst;
990 __ sub(tmp, scratch, Operand(src1, LSR, 31)); 1017 __ sub(tmp, scratch, Operand(src_exponent, LSR, 31));
991 __ cmp(tmp, Operand(30)); 1018 __ cmp(tmp, Operand(30));
992 __ b(gt, not_int32); 1019 __ b(gt, not_int32);
993 // - Bits [21:0] in the mantissa are not null. 1020 // - Bits [21:0] in the mantissa are not null.
994 __ tst(src2, Operand(0x3fffff)); 1021 __ tst(src_mantissa, Operand(0x3fffff));
995 __ b(ne, not_int32); 1022 __ b(ne, not_int32);
996 1023
997 // Otherwise the exponent needs to be big enough to shift left all the 1024 // Otherwise the exponent needs to be big enough to shift left all the
998 // non zero bits left. So we need the (30 - exponent) last bits of the 1025 // non zero bits left. So we need the (30 - exponent) last bits of the
999 // 31 higher bits of the mantissa to be null. 1026 // 31 higher bits of the mantissa to be null.
1000 // Because bits [21:0] are null, we can check instead that the 1027 // Because bits [21:0] are null, we can check instead that the
1001 // (32 - exponent) last bits of the 32 higher bits of the mantissa are null. 1028 // (32 - exponent) last bits of the 32 higher bits of the mantissa are null.
1002 1029
1003 // Get the 32 higher bits of the mantissa in dst. 1030 // Get the 32 higher bits of the mantissa in dst.
1004 __ Ubfx(dst, 1031 __ Ubfx(dst,
1005 src2, 1032 src_mantissa,
1006 HeapNumber::kMantissaBitsInTopWord, 1033 HeapNumber::kMantissaBitsInTopWord,
1007 32 - HeapNumber::kMantissaBitsInTopWord); 1034 32 - HeapNumber::kMantissaBitsInTopWord);
1008 __ orr(dst, 1035 __ orr(dst,
1009 dst, 1036 dst,
1010 Operand(src1, LSL, HeapNumber::kNonMantissaBitsInTopWord)); 1037 Operand(src_exponent, LSL, HeapNumber::kNonMantissaBitsInTopWord));
1011 1038
1012 // Create the mask and test the lower bits (of the higher bits). 1039 // Create the mask and test the lower bits (of the higher bits).
1013 __ rsb(scratch, scratch, Operand(32)); 1040 __ rsb(scratch, scratch, Operand(32));
1014 __ mov(src2, Operand(1)); 1041 __ mov(src_mantissa, Operand(1));
1015 __ mov(src1, Operand(src2, LSL, scratch)); 1042 __ mov(src_exponent, Operand(src_mantissa, LSL, scratch));
1016 __ sub(src1, src1, Operand(1)); 1043 __ sub(src_exponent, src_exponent, Operand(1));
1017 __ tst(dst, src1); 1044 __ tst(dst, src_exponent);
1018 __ b(ne, not_int32); 1045 __ b(ne, not_int32);
1019 } 1046 }
1020 1047
1021 1048
1022 void FloatingPointHelper::CallCCodeForDoubleOperation( 1049 void FloatingPointHelper::CallCCodeForDoubleOperation(
1023 MacroAssembler* masm, 1050 MacroAssembler* masm,
1024 Token::Value op, 1051 Token::Value op,
1025 Register heap_number_result, 1052 Register heap_number_result,
1026 Register scratch) { 1053 Register scratch) {
1027 // Using core registers: 1054 // Using core registers:
(...skipping 6559 matching lines...) Expand 10 before | Expand all | Expand 10 after
7587 7614
7588 __ Pop(lr, r5, r1); 7615 __ Pop(lr, r5, r1);
7589 __ Ret(); 7616 __ Ret();
7590 } 7617 }
7591 7618
7592 #undef __ 7619 #undef __
7593 7620
7594 } } // namespace v8::internal 7621 } } // namespace v8::internal
7595 7622
7596 #endif // V8_TARGET_ARCH_ARM 7623 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « no previous file | src/arm/stub-cache-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698