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 666 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
677 void FloatingPointHelper::LoadNumber(MacroAssembler* masm, | 677 void FloatingPointHelper::LoadNumber(MacroAssembler* masm, |
678 Destination destination, | 678 Destination destination, |
679 Register object, | 679 Register object, |
680 FPURegister dst, | 680 FPURegister dst, |
681 Register dst1, | 681 Register dst1, |
682 Register dst2, | 682 Register dst2, |
683 Register heap_number_map, | 683 Register heap_number_map, |
684 Register scratch1, | 684 Register scratch1, |
685 Register scratch2, | 685 Register scratch2, |
686 Label* not_number) { | 686 Label* not_number) { |
687 ASSERT(!object.is(dst1) && !object.is(dst2)); | |
688 | |
689 __ AssertRootValue(heap_number_map, | 687 __ AssertRootValue(heap_number_map, |
690 Heap::kHeapNumberMapRootIndex, | 688 Heap::kHeapNumberMapRootIndex, |
691 "HeapNumberMap register clobbered."); | 689 "HeapNumberMap register clobbered."); |
692 | 690 |
693 Label is_smi, done; | 691 Label is_smi, done; |
694 | 692 |
695 // Smi-check | 693 // Smi-check |
696 __ UntagAndJumpIfSmi(scratch1, object, &is_smi); | 694 __ UntagAndJumpIfSmi(scratch1, object, &is_smi); |
697 // Heap number check | 695 // Heap number check |
698 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_number); | 696 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_number); |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
835 // Clear the first non null bit. | 833 // Clear the first non null bit. |
836 __ li(scratch2, Operand(1)); | 834 __ li(scratch2, Operand(1)); |
837 __ sllv(scratch2, scratch2, dst_mantissa); | 835 __ sllv(scratch2, scratch2, dst_mantissa); |
838 __ li(at, -1); | 836 __ li(at, -1); |
839 __ Xor(scratch2, scratch2, at); | 837 __ Xor(scratch2, scratch2, at); |
840 __ And(int_scratch, int_scratch, scratch2); | 838 __ And(int_scratch, int_scratch, scratch2); |
841 | 839 |
842 // Get the number of bits to set in the lower part of the mantissa. | 840 // Get the number of bits to set in the lower part of the mantissa. |
843 __ Subu(scratch2, dst_mantissa, | 841 __ Subu(scratch2, dst_mantissa, |
844 Operand(HeapNumber::kMantissaBitsInTopWord)); | 842 Operand(HeapNumber::kMantissaBitsInTopWord)); |
845 __ Branch(&fewer_than_20_useful_bits, lt, scratch2, Operand(zero_reg)); | 843 __ Branch(&fewer_than_20_useful_bits, le, scratch2, Operand(zero_reg)); |
846 // Set the higher 20 bits of the mantissa. | 844 // Set the higher 20 bits of the mantissa. |
847 __ srlv(at, int_scratch, scratch2); | 845 __ srlv(at, int_scratch, scratch2); |
848 __ or_(dst_exponent, dst_exponent, at); | 846 __ or_(dst_exponent, dst_exponent, at); |
849 __ li(at, 32); | 847 __ li(at, 32); |
850 __ subu(scratch2, at, scratch2); | 848 __ subu(scratch2, at, scratch2); |
851 __ sllv(dst_mantissa, int_scratch, scratch2); | 849 __ sllv(dst_mantissa, int_scratch, scratch2); |
852 __ Branch(&done); | 850 __ Branch(&done); |
853 | 851 |
854 __ bind(&fewer_than_20_useful_bits); | 852 __ bind(&fewer_than_20_useful_bits); |
855 __ li(at, HeapNumber::kMantissaBitsInTopWord); | 853 __ li(at, HeapNumber::kMantissaBitsInTopWord); |
(...skipping 17 matching lines...) Expand all Loading... |
873 Register heap_number_map, | 871 Register heap_number_map, |
874 Register scratch1, | 872 Register scratch1, |
875 Register scratch2, | 873 Register scratch2, |
876 FPURegister single_scratch, | 874 FPURegister single_scratch, |
877 Label* not_int32) { | 875 Label* not_int32) { |
878 ASSERT(!scratch1.is(object) && !scratch2.is(object)); | 876 ASSERT(!scratch1.is(object) && !scratch2.is(object)); |
879 ASSERT(!scratch1.is(scratch2)); | 877 ASSERT(!scratch1.is(scratch2)); |
880 ASSERT(!heap_number_map.is(object) && | 878 ASSERT(!heap_number_map.is(object) && |
881 !heap_number_map.is(scratch1) && | 879 !heap_number_map.is(scratch1) && |
882 !heap_number_map.is(scratch2)); | 880 !heap_number_map.is(scratch2)); |
883 // ARM uses pop/push and Ldlr to save dst_* and probably object registers in | |
884 // softfloat path. On MIPS there is no ldlr, 1st lw instruction may overwrite | |
885 // object register making the 2nd lw invalid. | |
886 ASSERT(!object.is(dst_mantissa) && !object.is(dst_exponent)); | |
887 | 881 |
888 Label done, obj_is_not_smi; | 882 Label done, obj_is_not_smi; |
889 | 883 |
890 __ JumpIfNotSmi(object, &obj_is_not_smi); | 884 __ JumpIfNotSmi(object, &obj_is_not_smi); |
891 __ SmiUntag(scratch1, object); | 885 __ SmiUntag(scratch1, object); |
892 ConvertIntToDouble(masm, scratch1, destination, double_dst, dst_mantissa, | 886 ConvertIntToDouble(masm, scratch1, destination, double_dst, dst_mantissa, |
893 dst_exponent, scratch2, single_scratch); | 887 dst_exponent, scratch2, single_scratch); |
894 __ Branch(&done); | 888 __ Branch(&done); |
895 | 889 |
896 __ bind(&obj_is_not_smi); | 890 __ bind(&obj_is_not_smi); |
(...skipping 16 matching lines...) Expand all Loading... |
913 double_scratch, | 907 double_scratch, |
914 except_flag, | 908 except_flag, |
915 kCheckForInexactConversion); | 909 kCheckForInexactConversion); |
916 | 910 |
917 // Jump to not_int32 if the operation did not succeed. | 911 // Jump to not_int32 if the operation did not succeed. |
918 __ Branch(not_int32, ne, except_flag, Operand(zero_reg)); | 912 __ Branch(not_int32, ne, except_flag, Operand(zero_reg)); |
919 | 913 |
920 if (destination == kCoreRegisters) { | 914 if (destination == kCoreRegisters) { |
921 __ Move(dst_mantissa, dst_exponent, double_dst); | 915 __ Move(dst_mantissa, dst_exponent, double_dst); |
922 } | 916 } |
| 917 |
923 } else { | 918 } else { |
| 919 ASSERT(!scratch1.is(object) && !scratch2.is(object)); |
924 // Load the double value in the destination registers. | 920 // Load the double value in the destination registers. |
925 __ lw(dst_exponent, FieldMemOperand(object, HeapNumber::kExponentOffset)); | 921 bool save_registers = object.is(dst_mantissa) || object.is(dst_exponent); |
926 __ lw(dst_mantissa, FieldMemOperand(object, HeapNumber::kMantissaOffset)); | 922 if (save_registers) { |
| 923 // Save both output registers, because the other one probably holds |
| 924 // an important value too. |
| 925 __ Push(dst_exponent, dst_mantissa); |
| 926 } |
| 927 if (object.is(dst_mantissa)) { |
| 928 __ lw(dst_exponent, FieldMemOperand(object, HeapNumber::kExponentOffset)); |
| 929 __ lw(dst_mantissa, FieldMemOperand(object, HeapNumber::kMantissaOffset)); |
| 930 } else { |
| 931 __ lw(dst_mantissa, FieldMemOperand(object, HeapNumber::kMantissaOffset)); |
| 932 __ lw(dst_exponent, FieldMemOperand(object, HeapNumber::kExponentOffset)); |
| 933 } |
927 | 934 |
928 // Check for 0 and -0. | 935 // Check for 0 and -0. |
| 936 Label zero; |
929 __ And(scratch1, dst_exponent, Operand(~HeapNumber::kSignMask)); | 937 __ And(scratch1, dst_exponent, Operand(~HeapNumber::kSignMask)); |
930 __ Or(scratch1, scratch1, Operand(dst_mantissa)); | 938 __ Or(scratch1, scratch1, Operand(dst_mantissa)); |
931 __ Branch(&done, eq, scratch1, Operand(zero_reg)); | 939 __ Branch(&zero, eq, scratch1, Operand(zero_reg)); |
932 | 940 |
933 // Check that the value can be exactly represented by a 32-bit integer. | 941 // Check that the value can be exactly represented by a 32-bit integer. |
934 // Jump to not_int32 if that's not the case. | 942 // Jump to not_int32 if that's not the case. |
| 943 Label restore_input_and_miss; |
935 DoubleIs32BitInteger(masm, dst_exponent, dst_mantissa, scratch1, scratch2, | 944 DoubleIs32BitInteger(masm, dst_exponent, dst_mantissa, scratch1, scratch2, |
936 not_int32); | 945 &restore_input_and_miss); |
937 | 946 |
938 // dst_* were trashed. Reload the double value. | 947 // dst_* were trashed. Reload the double value. |
939 __ lw(dst_exponent, FieldMemOperand(object, HeapNumber::kExponentOffset)); | 948 if (save_registers) { |
940 __ lw(dst_mantissa, FieldMemOperand(object, HeapNumber::kMantissaOffset)); | 949 __ Pop(dst_exponent, dst_mantissa); |
| 950 } |
| 951 if (object.is(dst_mantissa)) { |
| 952 __ lw(dst_exponent, FieldMemOperand(object, HeapNumber::kExponentOffset)); |
| 953 __ lw(dst_mantissa, FieldMemOperand(object, HeapNumber::kMantissaOffset)); |
| 954 } else { |
| 955 __ lw(dst_mantissa, FieldMemOperand(object, HeapNumber::kMantissaOffset)); |
| 956 __ lw(dst_exponent, FieldMemOperand(object, HeapNumber::kExponentOffset)); |
| 957 } |
| 958 |
| 959 __ Branch(&done); |
| 960 |
| 961 __ bind(&restore_input_and_miss); |
| 962 if (save_registers) { |
| 963 __ Pop(dst_exponent, dst_mantissa); |
| 964 } |
| 965 __ Branch(not_int32); |
| 966 |
| 967 __ bind(&zero); |
| 968 if (save_registers) { |
| 969 __ Drop(2); |
| 970 } |
941 } | 971 } |
942 | 972 |
943 __ bind(&done); | 973 __ bind(&done); |
944 } | 974 } |
945 | 975 |
946 | 976 |
947 void FloatingPointHelper::LoadNumberAsInt32(MacroAssembler* masm, | 977 void FloatingPointHelper::LoadNumberAsInt32(MacroAssembler* masm, |
948 Register object, | 978 Register object, |
949 Register dst, | 979 Register dst, |
950 Register heap_number_map, | 980 Register heap_number_map, |
(...skipping 1730 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2681 if (right_type == BinaryOpIC::INT32) { | 2711 if (right_type == BinaryOpIC::INT32) { |
2682 FloatingPointHelper::LoadNumberAsInt32Double( | 2712 FloatingPointHelper::LoadNumberAsInt32Double( |
2683 masm, right, destination, f14, f16, a2, a3, heap_number_map, | 2713 masm, right, destination, f14, f16, a2, a3, heap_number_map, |
2684 scratch1, scratch2, f2, miss); | 2714 scratch1, scratch2, f2, miss); |
2685 } else { | 2715 } else { |
2686 Label* fail = (right_type == BinaryOpIC::NUMBER) ? miss : not_numbers; | 2716 Label* fail = (right_type == BinaryOpIC::NUMBER) ? miss : not_numbers; |
2687 FloatingPointHelper::LoadNumber( | 2717 FloatingPointHelper::LoadNumber( |
2688 masm, destination, right, f14, a2, a3, heap_number_map, | 2718 masm, destination, right, f14, a2, a3, heap_number_map, |
2689 scratch1, scratch2, fail); | 2719 scratch1, scratch2, fail); |
2690 } | 2720 } |
2691 // Use scratch3 as left in LoadNumber functions to avoid overwriting of | |
2692 // left (a0) register. | |
2693 __ mov(scratch3, left); | |
2694 | |
2695 // Load left operand to f12 or a0/a1. This keeps a0/a1 intact if it | 2721 // Load left operand to f12 or a0/a1. This keeps a0/a1 intact if it |
2696 // jumps to |miss|. | 2722 // jumps to |miss|. |
2697 if (left_type == BinaryOpIC::INT32) { | 2723 if (left_type == BinaryOpIC::INT32) { |
2698 FloatingPointHelper::LoadNumberAsInt32Double( | 2724 FloatingPointHelper::LoadNumberAsInt32Double( |
2699 masm, scratch3, destination, f12, f16, a0, a1, heap_number_map, | 2725 masm, left, destination, f12, f16, a0, a1, heap_number_map, |
2700 scratch1, scratch2, f2, miss); | 2726 scratch1, scratch2, f2, miss); |
2701 } else { | 2727 } else { |
2702 Label* fail = (left_type == BinaryOpIC::NUMBER) ? miss : not_numbers; | 2728 Label* fail = (left_type == BinaryOpIC::NUMBER) ? miss : not_numbers; |
2703 FloatingPointHelper::LoadNumber( | 2729 FloatingPointHelper::LoadNumber( |
2704 masm, destination, scratch3, f12, a0, a1, heap_number_map, | 2730 masm, destination, left, f12, a0, a1, heap_number_map, |
2705 scratch1, scratch2, fail); | 2731 scratch1, scratch2, fail); |
2706 } | 2732 } |
2707 } | 2733 } |
2708 | 2734 |
2709 // Calculate the result. | 2735 // Calculate the result. |
2710 if (destination == FloatingPointHelper::kFPURegisters) { | 2736 if (destination == FloatingPointHelper::kFPURegisters) { |
2711 // Using FPU registers: | 2737 // Using FPU registers: |
2712 // f12: Left value. | 2738 // f12: Left value. |
2713 // f14: Right value. | 2739 // f14: Right value. |
2714 CpuFeatureScope scope(masm, FPU); | 2740 CpuFeatureScope scope(masm, FPU); |
(...skipping 5440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8155 __ Pop(ra, t1, a1); | 8181 __ Pop(ra, t1, a1); |
8156 __ Ret(); | 8182 __ Ret(); |
8157 } | 8183 } |
8158 | 8184 |
8159 | 8185 |
8160 #undef __ | 8186 #undef __ |
8161 | 8187 |
8162 } } // namespace v8::internal | 8188 } } // namespace v8::internal |
8163 | 8189 |
8164 #endif // V8_TARGET_ARCH_MIPS | 8190 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |