OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 771 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
782 } | 782 } |
783 __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset)); | 783 __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset)); |
784 __ Ret(); | 784 __ Ret(); |
785 } | 785 } |
786 } | 786 } |
787 | 787 |
788 | 788 |
789 Runtime::FunctionId TranscendentalCacheStub::RuntimeFunction() { | 789 Runtime::FunctionId TranscendentalCacheStub::RuntimeFunction() { |
790 switch (type_) { | 790 switch (type_) { |
791 // Add more cases when necessary. | 791 // Add more cases when necessary. |
792 case TranscendentalCache::SIN: return Runtime::kMath_sin; | |
793 case TranscendentalCache::COS: return Runtime::kMath_cos; | |
794 case TranscendentalCache::TAN: return Runtime::kMath_tan; | |
795 case TranscendentalCache::LOG: return Runtime::kMath_log; | 792 case TranscendentalCache::LOG: return Runtime::kMath_log; |
796 default: | 793 default: |
797 UNIMPLEMENTED(); | 794 UNIMPLEMENTED(); |
798 return Runtime::kAbort; | 795 return Runtime::kAbort; |
799 } | 796 } |
800 } | 797 } |
801 | 798 |
802 | 799 |
803 void TranscendentalCacheStub::GenerateOperation( | 800 void TranscendentalCacheStub::GenerateOperation( |
804 MacroAssembler* masm, TranscendentalCache::Type type) { | 801 MacroAssembler* masm, TranscendentalCache::Type type) { |
805 // Registers: | 802 // Registers: |
806 // rax: Newly allocated HeapNumber, which must be preserved. | 803 // rax: Newly allocated HeapNumber, which must be preserved. |
807 // rbx: Bits of input double. Must be preserved. | 804 // rbx: Bits of input double. Must be preserved. |
808 // rcx: Pointer to cache entry. Must be preserved. | 805 // rcx: Pointer to cache entry. Must be preserved. |
809 // st(0): Input double | 806 // st(0): Input double |
810 Label done; | 807 ASSERT(type == TranscendentalCache::LOG); |
811 if (type == TranscendentalCache::SIN || | 808 __ fldln2(); |
812 type == TranscendentalCache::COS || | 809 __ fxch(); |
813 type == TranscendentalCache::TAN) { | 810 __ fyl2x(); |
814 // Both fsin and fcos require arguments in the range +/-2^63 and | |
815 // return NaN for infinities and NaN. They can share all code except | |
816 // the actual fsin/fcos operation. | |
817 Label in_range; | |
818 // If argument is outside the range -2^63..2^63, fsin/cos doesn't | |
819 // work. We must reduce it to the appropriate range. | |
820 __ movq(rdi, rbx); | |
821 // Move exponent and sign bits to low bits. | |
822 __ shr(rdi, Immediate(HeapNumber::kMantissaBits)); | |
823 // Remove sign bit. | |
824 __ andl(rdi, Immediate((1 << HeapNumber::kExponentBits) - 1)); | |
825 int supported_exponent_limit = (63 + HeapNumber::kExponentBias); | |
826 __ cmpl(rdi, Immediate(supported_exponent_limit)); | |
827 __ j(below, &in_range); | |
828 // Check for infinity and NaN. Both return NaN for sin. | |
829 __ cmpl(rdi, Immediate(0x7ff)); | |
830 Label non_nan_result; | |
831 __ j(not_equal, &non_nan_result, Label::kNear); | |
832 // Input is +/-Infinity or NaN. Result is NaN. | |
833 __ fstp(0); | |
834 // NaN is represented by 0x7ff8000000000000. | |
835 __ subq(rsp, Immediate(kPointerSize)); | |
836 __ movl(Operand(rsp, 4), Immediate(0x7ff80000)); | |
837 __ movl(Operand(rsp, 0), Immediate(0x00000000)); | |
838 __ fld_d(Operand(rsp, 0)); | |
839 __ addq(rsp, Immediate(kPointerSize)); | |
840 __ jmp(&done); | |
841 | |
842 __ bind(&non_nan_result); | |
843 | |
844 // Use fpmod to restrict argument to the range +/-2*PI. | |
845 __ movq(rdi, rax); // Save rax before using fnstsw_ax. | |
846 __ fldpi(); | |
847 __ fadd(0); | |
848 __ fld(1); | |
849 // FPU Stack: input, 2*pi, input. | |
850 { | |
851 Label no_exceptions; | |
852 __ fwait(); | |
853 __ fnstsw_ax(); | |
854 // Clear if Illegal Operand or Zero Division exceptions are set. | |
855 __ testl(rax, Immediate(5)); // #IO and #ZD flags of FPU status word. | |
856 __ j(zero, &no_exceptions); | |
857 __ fnclex(); | |
858 __ bind(&no_exceptions); | |
859 } | |
860 | |
861 // Compute st(0) % st(1) | |
862 { | |
863 Label partial_remainder_loop; | |
864 __ bind(&partial_remainder_loop); | |
865 __ fprem1(); | |
866 __ fwait(); | |
867 __ fnstsw_ax(); | |
868 __ testl(rax, Immediate(0x400)); // Check C2 bit of FPU status word. | |
869 // If C2 is set, computation only has partial result. Loop to | |
870 // continue computation. | |
871 __ j(not_zero, &partial_remainder_loop); | |
872 } | |
873 // FPU Stack: input, 2*pi, input % 2*pi | |
874 __ fstp(2); | |
875 // FPU Stack: input % 2*pi, 2*pi, | |
876 __ fstp(0); | |
877 // FPU Stack: input % 2*pi | |
878 __ movq(rax, rdi); // Restore rax, pointer to the new HeapNumber. | |
879 __ bind(&in_range); | |
880 switch (type) { | |
881 case TranscendentalCache::SIN: | |
882 __ fsin(); | |
883 break; | |
884 case TranscendentalCache::COS: | |
885 __ fcos(); | |
886 break; | |
887 case TranscendentalCache::TAN: | |
888 // FPTAN calculates tangent onto st(0) and pushes 1.0 onto the | |
889 // FP register stack. | |
890 __ fptan(); | |
891 __ fstp(0); // Pop FP register stack. | |
892 break; | |
893 default: | |
894 UNREACHABLE(); | |
895 } | |
896 __ bind(&done); | |
897 } else { | |
898 ASSERT(type == TranscendentalCache::LOG); | |
899 __ fldln2(); | |
900 __ fxch(); | |
901 __ fyl2x(); | |
902 } | |
903 } | 811 } |
904 | 812 |
905 | 813 |
906 void FloatingPointHelper::LoadSSE2UnknownOperands(MacroAssembler* masm, | 814 void FloatingPointHelper::LoadSSE2UnknownOperands(MacroAssembler* masm, |
907 Label* not_numbers) { | 815 Label* not_numbers) { |
908 Label load_smi_rdx, load_nonsmi_rax, load_smi_rax, load_float_rax, done; | 816 Label load_smi_rdx, load_nonsmi_rax, load_smi_rax, load_float_rax, done; |
909 // Load operand in rdx into xmm0, or branch to not_numbers. | 817 // Load operand in rdx into xmm0, or branch to not_numbers. |
910 __ LoadRoot(rcx, Heap::kHeapNumberMapRootIndex); | 818 __ LoadRoot(rcx, Heap::kHeapNumberMapRootIndex); |
911 __ JumpIfSmi(rdx, &load_smi_rdx); | 819 __ JumpIfSmi(rdx, &load_smi_rdx); |
912 __ cmpq(FieldOperand(rdx, HeapObject::kMapOffset), rcx); | 820 __ cmpq(FieldOperand(rdx, HeapObject::kMapOffset), rcx); |
(...skipping 4870 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5783 __ bind(&fast_elements_case); | 5691 __ bind(&fast_elements_case); |
5784 GenerateCase(masm, FAST_ELEMENTS); | 5692 GenerateCase(masm, FAST_ELEMENTS); |
5785 } | 5693 } |
5786 | 5694 |
5787 | 5695 |
5788 #undef __ | 5696 #undef __ |
5789 | 5697 |
5790 } } // namespace v8::internal | 5698 } } // namespace v8::internal |
5791 | 5699 |
5792 #endif // V8_TARGET_ARCH_X64 | 5700 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |