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); |
} |