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 |
687 __ AssertRootValue(heap_number_map, | 689 __ AssertRootValue(heap_number_map, |
688 Heap::kHeapNumberMapRootIndex, | 690 Heap::kHeapNumberMapRootIndex, |
689 "HeapNumberMap register clobbered."); | 691 "HeapNumberMap register clobbered."); |
690 | 692 |
691 Label is_smi, done; | 693 Label is_smi, done; |
692 | 694 |
693 // Smi-check | 695 // Smi-check |
694 __ UntagAndJumpIfSmi(scratch1, object, &is_smi); | 696 __ UntagAndJumpIfSmi(scratch1, object, &is_smi); |
695 // Heap number check | 697 // Heap number check |
696 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_number); | 698 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_number); |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
871 Register heap_number_map, | 873 Register heap_number_map, |
872 Register scratch1, | 874 Register scratch1, |
873 Register scratch2, | 875 Register scratch2, |
874 FPURegister single_scratch, | 876 FPURegister single_scratch, |
875 Label* not_int32) { | 877 Label* not_int32) { |
876 ASSERT(!scratch1.is(object) && !scratch2.is(object)); | 878 ASSERT(!scratch1.is(object) && !scratch2.is(object)); |
877 ASSERT(!scratch1.is(scratch2)); | 879 ASSERT(!scratch1.is(scratch2)); |
878 ASSERT(!heap_number_map.is(object) && | 880 ASSERT(!heap_number_map.is(object) && |
879 !heap_number_map.is(scratch1) && | 881 !heap_number_map.is(scratch1) && |
880 !heap_number_map.is(scratch2)); | 882 !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)); |
881 | 887 |
882 Label done, obj_is_not_smi; | 888 Label done, obj_is_not_smi; |
883 | 889 |
884 __ JumpIfNotSmi(object, &obj_is_not_smi); | 890 __ JumpIfNotSmi(object, &obj_is_not_smi); |
885 __ SmiUntag(scratch1, object); | 891 __ SmiUntag(scratch1, object); |
886 ConvertIntToDouble(masm, scratch1, destination, double_dst, dst_mantissa, | 892 ConvertIntToDouble(masm, scratch1, destination, double_dst, dst_mantissa, |
887 dst_exponent, scratch2, single_scratch); | 893 dst_exponent, scratch2, single_scratch); |
888 __ Branch(&done); | 894 __ Branch(&done); |
889 | 895 |
890 __ bind(&obj_is_not_smi); | 896 __ bind(&obj_is_not_smi); |
(...skipping 16 matching lines...) Expand all Loading... |
907 double_scratch, | 913 double_scratch, |
908 except_flag, | 914 except_flag, |
909 kCheckForInexactConversion); | 915 kCheckForInexactConversion); |
910 | 916 |
911 // Jump to not_int32 if the operation did not succeed. | 917 // Jump to not_int32 if the operation did not succeed. |
912 __ Branch(not_int32, ne, except_flag, Operand(zero_reg)); | 918 __ Branch(not_int32, ne, except_flag, Operand(zero_reg)); |
913 | 919 |
914 if (destination == kCoreRegisters) { | 920 if (destination == kCoreRegisters) { |
915 __ Move(dst_mantissa, dst_exponent, double_dst); | 921 __ Move(dst_mantissa, dst_exponent, double_dst); |
916 } | 922 } |
917 | |
918 } else { | 923 } else { |
919 ASSERT(!scratch1.is(object) && !scratch2.is(object)); | |
920 // Load the double value in the destination registers. | 924 // Load the double value in the destination registers. |
921 bool save_registers = object.is(dst_mantissa) || object.is(dst_exponent); | |
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 __ lw(dst_exponent, FieldMemOperand(object, HeapNumber::kExponentOffset)); | 925 __ lw(dst_exponent, FieldMemOperand(object, HeapNumber::kExponentOffset)); |
928 __ lw(dst_mantissa, FieldMemOperand(object, HeapNumber::kMantissaOffset)); | 926 __ lw(dst_mantissa, FieldMemOperand(object, HeapNumber::kMantissaOffset)); |
929 | 927 |
930 // Check for 0 and -0. | 928 // Check for 0 and -0. |
931 Label zero; | |
932 __ And(scratch1, dst_exponent, Operand(~HeapNumber::kSignMask)); | 929 __ And(scratch1, dst_exponent, Operand(~HeapNumber::kSignMask)); |
933 __ Or(scratch1, scratch1, Operand(dst_mantissa)); | 930 __ Or(scratch1, scratch1, Operand(dst_mantissa)); |
934 __ Branch(&zero, eq, scratch1, Operand(zero_reg)); | 931 __ Branch(&done, eq, scratch1, Operand(zero_reg)); |
935 | 932 |
936 // Check that the value can be exactly represented by a 32-bit integer. | 933 // Check that the value can be exactly represented by a 32-bit integer. |
937 // Jump to not_int32 if that's not the case. | 934 // Jump to not_int32 if that's not the case. |
938 Label restore_input_and_miss; | |
939 DoubleIs32BitInteger(masm, dst_exponent, dst_mantissa, scratch1, scratch2, | 935 DoubleIs32BitInteger(masm, dst_exponent, dst_mantissa, scratch1, scratch2, |
940 &restore_input_and_miss); | 936 not_int32); |
941 | 937 |
942 // dst_* were trashed. Reload the double value. | 938 // dst_* were trashed. Reload the double value. |
943 if (save_registers) { | |
944 __ Pop(dst_exponent, dst_mantissa); | |
945 } | |
946 __ lw(dst_exponent, FieldMemOperand(object, HeapNumber::kExponentOffset)); | 939 __ lw(dst_exponent, FieldMemOperand(object, HeapNumber::kExponentOffset)); |
947 __ lw(dst_mantissa, FieldMemOperand(object, HeapNumber::kMantissaOffset)); | 940 __ lw(dst_mantissa, FieldMemOperand(object, HeapNumber::kMantissaOffset)); |
948 __ Branch(&done); | |
949 | |
950 __ bind(&restore_input_and_miss); | |
951 if (save_registers) { | |
952 __ Pop(dst_exponent, dst_mantissa); | |
953 } | |
954 __ Branch(not_int32); | |
955 | |
956 __ bind(&zero); | |
957 if (save_registers) { | |
958 __ Drop(2); | |
959 } | |
960 } | 941 } |
961 | 942 |
962 __ bind(&done); | 943 __ bind(&done); |
963 } | 944 } |
964 | 945 |
965 | 946 |
966 void FloatingPointHelper::LoadNumberAsInt32(MacroAssembler* masm, | 947 void FloatingPointHelper::LoadNumberAsInt32(MacroAssembler* masm, |
967 Register object, | 948 Register object, |
968 Register dst, | 949 Register dst, |
969 Register heap_number_map, | 950 Register heap_number_map, |
(...skipping 1730 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2700 if (right_type == BinaryOpIC::INT32) { | 2681 if (right_type == BinaryOpIC::INT32) { |
2701 FloatingPointHelper::LoadNumberAsInt32Double( | 2682 FloatingPointHelper::LoadNumberAsInt32Double( |
2702 masm, right, destination, f14, f16, a2, a3, heap_number_map, | 2683 masm, right, destination, f14, f16, a2, a3, heap_number_map, |
2703 scratch1, scratch2, f2, miss); | 2684 scratch1, scratch2, f2, miss); |
2704 } else { | 2685 } else { |
2705 Label* fail = (right_type == BinaryOpIC::NUMBER) ? miss : not_numbers; | 2686 Label* fail = (right_type == BinaryOpIC::NUMBER) ? miss : not_numbers; |
2706 FloatingPointHelper::LoadNumber( | 2687 FloatingPointHelper::LoadNumber( |
2707 masm, destination, right, f14, a2, a3, heap_number_map, | 2688 masm, destination, right, f14, a2, a3, heap_number_map, |
2708 scratch1, scratch2, fail); | 2689 scratch1, scratch2, fail); |
2709 } | 2690 } |
| 2691 // Use scratch3 as left in LoadNumber functions to avoid overwriting of |
| 2692 // left (a0) register. |
| 2693 __ mov(scratch3, left); |
| 2694 |
2710 // Load left operand to f12 or a0/a1. This keeps a0/a1 intact if it | 2695 // Load left operand to f12 or a0/a1. This keeps a0/a1 intact if it |
2711 // jumps to |miss|. | 2696 // jumps to |miss|. |
2712 if (left_type == BinaryOpIC::INT32) { | 2697 if (left_type == BinaryOpIC::INT32) { |
2713 FloatingPointHelper::LoadNumberAsInt32Double( | 2698 FloatingPointHelper::LoadNumberAsInt32Double( |
2714 masm, left, destination, f12, f16, a0, a1, heap_number_map, | 2699 masm, scratch3, destination, f12, f16, a0, a1, heap_number_map, |
2715 scratch1, scratch2, f2, miss); | 2700 scratch1, scratch2, f2, miss); |
2716 } else { | 2701 } else { |
2717 Label* fail = (left_type == BinaryOpIC::NUMBER) ? miss : not_numbers; | 2702 Label* fail = (left_type == BinaryOpIC::NUMBER) ? miss : not_numbers; |
2718 FloatingPointHelper::LoadNumber( | 2703 FloatingPointHelper::LoadNumber( |
2719 masm, destination, left, f12, a0, a1, heap_number_map, | 2704 masm, destination, scratch3, f12, a0, a1, heap_number_map, |
2720 scratch1, scratch2, fail); | 2705 scratch1, scratch2, fail); |
2721 } | 2706 } |
2722 } | 2707 } |
2723 | 2708 |
2724 // Calculate the result. | 2709 // Calculate the result. |
2725 if (destination == FloatingPointHelper::kFPURegisters) { | 2710 if (destination == FloatingPointHelper::kFPURegisters) { |
2726 // Using FPU registers: | 2711 // Using FPU registers: |
2727 // f12: Left value. | 2712 // f12: Left value. |
2728 // f14: Right value. | 2713 // f14: Right value. |
2729 CpuFeatureScope scope(masm, FPU); | 2714 CpuFeatureScope scope(masm, FPU); |
(...skipping 5466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8196 __ Pop(ra, t1, a1); | 8181 __ Pop(ra, t1, a1); |
8197 __ Ret(); | 8182 __ Ret(); |
8198 } | 8183 } |
8199 | 8184 |
8200 | 8185 |
8201 #undef __ | 8186 #undef __ |
8202 | 8187 |
8203 } } // namespace v8::internal | 8188 } } // namespace v8::internal |
8204 | 8189 |
8205 #endif // V8_TARGET_ARCH_MIPS | 8190 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |