| 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 |