| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 2492 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2503 // This gives slightly larger code. | 2503 // This gives slightly larger code. |
| 2504 if (tagged) { | 2504 if (tagged) { |
| 2505 __ AllocateHeapNumber(eax, edi, no_reg, &runtime_call_clear_stack); | 2505 __ AllocateHeapNumber(eax, edi, no_reg, &runtime_call_clear_stack); |
| 2506 } else { // UNTAGGED. | 2506 } else { // UNTAGGED. |
| 2507 __ AllocateHeapNumber(eax, edi, no_reg, &skip_cache); | 2507 __ AllocateHeapNumber(eax, edi, no_reg, &skip_cache); |
| 2508 __ sub(esp, Immediate(kDoubleSize)); | 2508 __ sub(esp, Immediate(kDoubleSize)); |
| 2509 __ movdbl(Operand(esp, 0), xmm1); | 2509 __ movdbl(Operand(esp, 0), xmm1); |
| 2510 __ fld_d(Operand(esp, 0)); | 2510 __ fld_d(Operand(esp, 0)); |
| 2511 __ add(esp, Immediate(kDoubleSize)); | 2511 __ add(esp, Immediate(kDoubleSize)); |
| 2512 } | 2512 } |
| 2513 GenerateOperation(masm); | 2513 GenerateOperation(masm, type_); |
| 2514 __ mov(Operand(ecx, 0), ebx); | 2514 __ mov(Operand(ecx, 0), ebx); |
| 2515 __ mov(Operand(ecx, kIntSize), edx); | 2515 __ mov(Operand(ecx, kIntSize), edx); |
| 2516 __ mov(Operand(ecx, 2 * kIntSize), eax); | 2516 __ mov(Operand(ecx, 2 * kIntSize), eax); |
| 2517 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 2517 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
| 2518 if (tagged) { | 2518 if (tagged) { |
| 2519 __ ret(kPointerSize); | 2519 __ ret(kPointerSize); |
| 2520 } else { // UNTAGGED. | 2520 } else { // UNTAGGED. |
| 2521 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); | 2521 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); |
| 2522 __ Ret(); | 2522 __ Ret(); |
| 2523 | 2523 |
| 2524 // Skip cache and return answer directly, only in untagged case. | 2524 // Skip cache and return answer directly, only in untagged case. |
| 2525 __ bind(&skip_cache); | 2525 __ bind(&skip_cache); |
| 2526 __ sub(esp, Immediate(kDoubleSize)); | 2526 __ sub(esp, Immediate(kDoubleSize)); |
| 2527 __ movdbl(Operand(esp, 0), xmm1); | 2527 __ movdbl(Operand(esp, 0), xmm1); |
| 2528 __ fld_d(Operand(esp, 0)); | 2528 __ fld_d(Operand(esp, 0)); |
| 2529 GenerateOperation(masm); | 2529 GenerateOperation(masm, type_); |
| 2530 __ fstp_d(Operand(esp, 0)); | 2530 __ fstp_d(Operand(esp, 0)); |
| 2531 __ movdbl(xmm1, Operand(esp, 0)); | 2531 __ movdbl(xmm1, Operand(esp, 0)); |
| 2532 __ add(esp, Immediate(kDoubleSize)); | 2532 __ add(esp, Immediate(kDoubleSize)); |
| 2533 // We return the value in xmm1 without adding it to the cache, but | 2533 // We return the value in xmm1 without adding it to the cache, but |
| 2534 // we cause a scavenging GC so that future allocations will succeed. | 2534 // we cause a scavenging GC so that future allocations will succeed. |
| 2535 { | 2535 { |
| 2536 FrameScope scope(masm, StackFrame::INTERNAL); | 2536 FrameScope scope(masm, StackFrame::INTERNAL); |
| 2537 // Allocate an unused object bigger than a HeapNumber. | 2537 // Allocate an unused object bigger than a HeapNumber. |
| 2538 __ push(Immediate(Smi::FromInt(2 * kDoubleSize))); | 2538 __ push(Immediate(Smi::FromInt(2 * kDoubleSize))); |
| 2539 __ CallRuntimeSaveDoubles(Runtime::kAllocateInNewSpace); | 2539 __ CallRuntimeSaveDoubles(Runtime::kAllocateInNewSpace); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2571 case TranscendentalCache::COS: return Runtime::kMath_cos; | 2571 case TranscendentalCache::COS: return Runtime::kMath_cos; |
| 2572 case TranscendentalCache::TAN: return Runtime::kMath_tan; | 2572 case TranscendentalCache::TAN: return Runtime::kMath_tan; |
| 2573 case TranscendentalCache::LOG: return Runtime::kMath_log; | 2573 case TranscendentalCache::LOG: return Runtime::kMath_log; |
| 2574 default: | 2574 default: |
| 2575 UNIMPLEMENTED(); | 2575 UNIMPLEMENTED(); |
| 2576 return Runtime::kAbort; | 2576 return Runtime::kAbort; |
| 2577 } | 2577 } |
| 2578 } | 2578 } |
| 2579 | 2579 |
| 2580 | 2580 |
| 2581 void TranscendentalCacheStub::GenerateOperation(MacroAssembler* masm) { | 2581 void TranscendentalCacheStub::GenerateOperation( |
| 2582 MacroAssembler* masm, TranscendentalCache::Type type) { |
| 2582 // Only free register is edi. | 2583 // Only free register is edi. |
| 2583 // Input value is on FP stack, and also in ebx/edx. | 2584 // Input value is on FP stack, and also in ebx/edx. |
| 2584 // Input value is possibly in xmm1. | 2585 // Input value is possibly in xmm1. |
| 2585 // Address of result (a newly allocated HeapNumber) may be in eax. | 2586 // Address of result (a newly allocated HeapNumber) may be in eax. |
| 2586 if (type_ == TranscendentalCache::SIN || | 2587 if (type == TranscendentalCache::SIN || |
| 2587 type_ == TranscendentalCache::COS || | 2588 type == TranscendentalCache::COS || |
| 2588 type_ == TranscendentalCache::TAN) { | 2589 type == TranscendentalCache::TAN) { |
| 2589 // Both fsin and fcos require arguments in the range +/-2^63 and | 2590 // Both fsin and fcos require arguments in the range +/-2^63 and |
| 2590 // return NaN for infinities and NaN. They can share all code except | 2591 // return NaN for infinities and NaN. They can share all code except |
| 2591 // the actual fsin/fcos operation. | 2592 // the actual fsin/fcos operation. |
| 2592 Label in_range, done; | 2593 Label in_range, done; |
| 2593 // If argument is outside the range -2^63..2^63, fsin/cos doesn't | 2594 // If argument is outside the range -2^63..2^63, fsin/cos doesn't |
| 2594 // work. We must reduce it to the appropriate range. | 2595 // work. We must reduce it to the appropriate range. |
| 2595 __ mov(edi, edx); | 2596 __ mov(edi, edx); |
| 2596 __ and_(edi, Immediate(0x7ff00000)); // Exponent only. | 2597 __ and_(edi, Immediate(0x7ff00000)); // Exponent only. |
| 2597 int supported_exponent_limit = | 2598 int supported_exponent_limit = |
| 2598 (63 + HeapNumber::kExponentBias) << HeapNumber::kExponentShift; | 2599 (63 + HeapNumber::kExponentBias) << HeapNumber::kExponentShift; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2642 // continue computation. | 2643 // continue computation. |
| 2643 __ j(not_zero, &partial_remainder_loop); | 2644 __ j(not_zero, &partial_remainder_loop); |
| 2644 } | 2645 } |
| 2645 // FPU Stack: input, 2*pi, input % 2*pi | 2646 // FPU Stack: input, 2*pi, input % 2*pi |
| 2646 __ fstp(2); | 2647 __ fstp(2); |
| 2647 __ fstp(0); | 2648 __ fstp(0); |
| 2648 __ mov(eax, edi); // Restore eax (allocated HeapNumber pointer). | 2649 __ mov(eax, edi); // Restore eax (allocated HeapNumber pointer). |
| 2649 | 2650 |
| 2650 // FPU Stack: input % 2*pi | 2651 // FPU Stack: input % 2*pi |
| 2651 __ bind(&in_range); | 2652 __ bind(&in_range); |
| 2652 switch (type_) { | 2653 switch (type) { |
| 2653 case TranscendentalCache::SIN: | 2654 case TranscendentalCache::SIN: |
| 2654 __ fsin(); | 2655 __ fsin(); |
| 2655 break; | 2656 break; |
| 2656 case TranscendentalCache::COS: | 2657 case TranscendentalCache::COS: |
| 2657 __ fcos(); | 2658 __ fcos(); |
| 2658 break; | 2659 break; |
| 2659 case TranscendentalCache::TAN: | 2660 case TranscendentalCache::TAN: |
| 2660 // FPTAN calculates tangent onto st(0) and pushes 1.0 onto the | 2661 // FPTAN calculates tangent onto st(0) and pushes 1.0 onto the |
| 2661 // FP register stack. | 2662 // FP register stack. |
| 2662 __ fptan(); | 2663 __ fptan(); |
| 2663 __ fstp(0); // Pop FP register stack. | 2664 __ fstp(0); // Pop FP register stack. |
| 2664 break; | 2665 break; |
| 2665 default: | 2666 default: |
| 2666 UNREACHABLE(); | 2667 UNREACHABLE(); |
| 2667 } | 2668 } |
| 2668 __ bind(&done); | 2669 __ bind(&done); |
| 2669 } else { | 2670 } else { |
| 2670 ASSERT(type_ == TranscendentalCache::LOG); | 2671 ASSERT(type == TranscendentalCache::LOG); |
| 2671 __ fldln2(); | 2672 __ fldln2(); |
| 2672 __ fxch(); | 2673 __ fxch(); |
| 2673 __ fyl2x(); | 2674 __ fyl2x(); |
| 2674 } | 2675 } |
| 2675 } | 2676 } |
| 2676 | 2677 |
| 2677 | 2678 |
| 2678 // Input: edx, eax are the left and right objects of a bit op. | 2679 // Input: edx, eax are the left and right objects of a bit op. |
| 2679 // Output: eax, ecx are left and right integers for a bit op. | 2680 // Output: eax, ecx are left and right integers for a bit op. |
| 2680 void FloatingPointHelper::LoadUnknownsAsIntegers(MacroAssembler* masm, | 2681 void FloatingPointHelper::LoadUnknownsAsIntegers(MacroAssembler* masm, |
| (...skipping 4718 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7399 false); | 7400 false); |
| 7400 __ pop(edx); | 7401 __ pop(edx); |
| 7401 __ ret(0); | 7402 __ ret(0); |
| 7402 } | 7403 } |
| 7403 | 7404 |
| 7404 #undef __ | 7405 #undef __ |
| 7405 | 7406 |
| 7406 } } // namespace v8::internal | 7407 } } // namespace v8::internal |
| 7407 | 7408 |
| 7408 #endif // V8_TARGET_ARCH_IA32 | 7409 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |