| Index: src/x64/code-stubs-x64.cc
|
| ===================================================================
|
| --- src/x64/code-stubs-x64.cc (revision 5911)
|
| +++ src/x64/code-stubs-x64.cc (working copy)
|
| @@ -1107,6 +1107,7 @@
|
| // Add more cases when necessary.
|
| case TranscendentalCache::SIN: return Runtime::kMath_sin;
|
| case TranscendentalCache::COS: return Runtime::kMath_cos;
|
| + case TranscendentalCache::LOG: return Runtime::kMath_log;
|
| default:
|
| UNIMPLEMENTED();
|
| return Runtime::kAbort;
|
| @@ -1121,73 +1122,76 @@
|
| // rcx: Pointer to cache entry. Must be preserved.
|
| // st(0): Input double
|
| Label done;
|
| - ASSERT(type_ == TranscendentalCache::SIN ||
|
| - type_ == TranscendentalCache::COS);
|
| - // More transcendental types can be added later.
|
| + if (type_ == TranscendentalCache::SIN || type_ == TranscendentalCache::COS) {
|
| + // Both fsin and fcos require arguments in the range +/-2^63 and
|
| + // return NaN for infinities and NaN. They can share all code except
|
| + // the actual fsin/fcos operation.
|
| + Label in_range;
|
| + // If argument is outside the range -2^63..2^63, fsin/cos doesn't
|
| + // work. We must reduce it to the appropriate range.
|
| + __ movq(rdi, rbx);
|
| + // Move exponent and sign bits to low bits.
|
| + __ shr(rdi, Immediate(HeapNumber::kMantissaBits));
|
| + // Remove sign bit.
|
| + __ andl(rdi, Immediate((1 << HeapNumber::kExponentBits) - 1));
|
| + int supported_exponent_limit = (63 + HeapNumber::kExponentBias);
|
| + __ cmpl(rdi, Immediate(supported_exponent_limit));
|
| + __ j(below, &in_range);
|
| + // Check for infinity and NaN. Both return NaN for sin.
|
| + __ cmpl(rdi, Immediate(0x7ff));
|
| + __ j(equal, on_nan_result);
|
|
|
| - // Both fsin and fcos require arguments in the range +/-2^63 and
|
| - // return NaN for infinities and NaN. They can share all code except
|
| - // the actual fsin/fcos operation.
|
| - Label in_range;
|
| - // If argument is outside the range -2^63..2^63, fsin/cos doesn't
|
| - // work. We must reduce it to the appropriate range.
|
| - __ movq(rdi, rbx);
|
| - // Move exponent and sign bits to low bits.
|
| - __ shr(rdi, Immediate(HeapNumber::kMantissaBits));
|
| - // Remove sign bit.
|
| - __ andl(rdi, Immediate((1 << HeapNumber::kExponentBits) - 1));
|
| - int supported_exponent_limit = (63 + HeapNumber::kExponentBias);
|
| - __ cmpl(rdi, Immediate(supported_exponent_limit));
|
| - __ j(below, &in_range);
|
| - // Check for infinity and NaN. Both return NaN for sin.
|
| - __ cmpl(rdi, Immediate(0x7ff));
|
| - __ j(equal, on_nan_result);
|
| + // Use fpmod to restrict argument to the range +/-2*PI.
|
| + __ fldpi();
|
| + __ fadd(0);
|
| + __ fld(1);
|
| + // FPU Stack: input, 2*pi, input.
|
| + {
|
| + Label no_exceptions;
|
| + __ fwait();
|
| + __ fnstsw_ax();
|
| + // Clear if Illegal Operand or Zero Division exceptions are set.
|
| + __ testl(rax, Immediate(5)); // #IO and #ZD flags of FPU status word.
|
| + __ j(zero, &no_exceptions);
|
| + __ fnclex();
|
| + __ bind(&no_exceptions);
|
| + }
|
|
|
| - // Use fpmod to restrict argument to the range +/-2*PI.
|
| - __ fldpi();
|
| - __ fadd(0);
|
| - __ fld(1);
|
| - // FPU Stack: input, 2*pi, input.
|
| - {
|
| - Label no_exceptions;
|
| - __ fwait();
|
| - __ fnstsw_ax();
|
| - // Clear if Illegal Operand or Zero Division exceptions are set.
|
| - __ testl(rax, Immediate(5)); // #IO and #ZD flags of FPU status word.
|
| - __ j(zero, &no_exceptions);
|
| - __ fnclex();
|
| - __ bind(&no_exceptions);
|
| + // Compute st(0) % st(1)
|
| + {
|
| + NearLabel partial_remainder_loop;
|
| + __ bind(&partial_remainder_loop);
|
| + __ fprem1();
|
| + __ fwait();
|
| + __ fnstsw_ax();
|
| + __ testl(rax, Immediate(0x400)); // Check C2 bit of FPU status word.
|
| + // If C2 is set, computation only has partial result. Loop to
|
| + // continue computation.
|
| + __ j(not_zero, &partial_remainder_loop);
|
| }
|
| -
|
| - // Compute st(0) % st(1)
|
| - {
|
| - NearLabel partial_remainder_loop;
|
| - __ bind(&partial_remainder_loop);
|
| - __ fprem1();
|
| - __ fwait();
|
| - __ fnstsw_ax();
|
| - __ testl(rax, Immediate(0x400)); // Check C2 bit of FPU status word.
|
| - // If C2 is set, computation only has partial result. Loop to
|
| - // continue computation.
|
| - __ j(not_zero, &partial_remainder_loop);
|
| + // FPU Stack: input, 2*pi, input % 2*pi
|
| + __ fstp(2);
|
| + // FPU Stack: input % 2*pi, 2*pi,
|
| + __ fstp(0);
|
| + // FPU Stack: input % 2*pi
|
| + __ bind(&in_range);
|
| + switch (type_) {
|
| + case TranscendentalCache::SIN:
|
| + __ fsin();
|
| + break;
|
| + case TranscendentalCache::COS:
|
| + __ fcos();
|
| + break;
|
| + default:
|
| + UNREACHABLE();
|
| + }
|
| + __ bind(&done);
|
| + } else {
|
| + ASSERT(type_ == TranscendentalCache::LOG);
|
| + __ fldln2();
|
| + __ fxch();
|
| + __ fyl2x();
|
| }
|
| - // FPU Stack: input, 2*pi, input % 2*pi
|
| - __ fstp(2);
|
| - // FPU Stack: input % 2*pi, 2*pi,
|
| - __ fstp(0);
|
| - // FPU Stack: input % 2*pi
|
| - __ bind(&in_range);
|
| - switch (type_) {
|
| - case TranscendentalCache::SIN:
|
| - __ fsin();
|
| - break;
|
| - case TranscendentalCache::COS:
|
| - __ fcos();
|
| - break;
|
| - default:
|
| - UNREACHABLE();
|
| - }
|
| - __ bind(&done);
|
| }
|
|
|
|
|
|
|