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