OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 3574 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3585 } | 3585 } |
3586 } | 3586 } |
3587 | 3587 |
3588 | 3588 |
3589 void StackCheckStub::Generate(MacroAssembler* masm) { | 3589 void StackCheckStub::Generate(MacroAssembler* masm) { |
3590 __ TailCallRuntime(Runtime::kStackGuard, 0, 1); | 3590 __ TailCallRuntime(Runtime::kStackGuard, 0, 1); |
3591 } | 3591 } |
3592 | 3592 |
3593 | 3593 |
3594 void MathPowStub::Generate(MacroAssembler* masm) { | 3594 void MathPowStub::Generate(MacroAssembler* masm) { |
3595 Label call_runtime; | 3595 CpuFeatures::Scope fpu_scope(FPU); |
3596 | 3596 const Register base = a1; |
3597 if (CpuFeatures::IsSupported(FPU)) { | 3597 const Register exponent = a2; |
3598 CpuFeatures::Scope scope(FPU); | 3598 const Register heapnumbermap = t1; |
3599 | 3599 const Register heapnumber = v0; |
3600 Label base_not_smi; | 3600 const DoubleRegister double_base = f2; |
3601 Label exponent_not_smi; | 3601 const DoubleRegister double_exponent = f4; |
3602 Label convert_exponent; | 3602 const DoubleRegister double_result = f0; |
3603 | 3603 const DoubleRegister double_scratch = f6; |
3604 const Register base = a0; | 3604 const FPURegister single_scratch = f8; |
3605 const Register exponent = a2; | 3605 const Register scratch = t5; |
3606 const Register heapnumbermap = t1; | 3606 const Register scratch2 = t3; |
3607 const Register heapnumber = s0; // Callee-saved register. | 3607 |
3608 const Register scratch = t2; | 3608 Label call_runtime, done, exponent_not_smi, int_exponent; |
3609 const Register scratch2 = t3; | 3609 if (exponent_type_ == ON_STACK) { |
3610 | 3610 Label base_is_smi, unpack_exponent; |
3611 // Alocate FP values in the ABI-parameter-passing regs. | 3611 // The exponent and base are supplied as arguments on the stack. |
3612 const DoubleRegister double_base = f12; | 3612 // This can only happen if the stub is called from non-optimized code. |
3613 const DoubleRegister double_exponent = f14; | 3613 // Load input parameters from stack to double registers. |
3614 const DoubleRegister double_result = f0; | |
3615 const DoubleRegister double_scratch = f2; | |
3616 | |
3617 __ LoadRoot(heapnumbermap, Heap::kHeapNumberMapRootIndex); | |
3618 __ lw(base, MemOperand(sp, 1 * kPointerSize)); | 3614 __ lw(base, MemOperand(sp, 1 * kPointerSize)); |
3619 __ lw(exponent, MemOperand(sp, 0 * kPointerSize)); | 3615 __ lw(exponent, MemOperand(sp, 0 * kPointerSize)); |
3620 | 3616 |
3621 // Convert base to double value and store it in f0. | 3617 __ LoadRoot(heapnumbermap, Heap::kHeapNumberMapRootIndex); |
3622 __ JumpIfNotSmi(base, &base_not_smi); | 3618 |
3623 // Base is a Smi. Untag and convert it. | 3619 __ JumpIfSmi(base, &base_is_smi); |
3624 __ SmiUntag(base); | |
3625 __ mtc1(base, double_scratch); | |
3626 __ cvt_d_w(double_base, double_scratch); | |
3627 __ Branch(&convert_exponent); | |
3628 | |
3629 __ bind(&base_not_smi); | |
3630 __ lw(scratch, FieldMemOperand(base, JSObject::kMapOffset)); | 3620 __ lw(scratch, FieldMemOperand(base, JSObject::kMapOffset)); |
3631 __ Branch(&call_runtime, ne, scratch, Operand(heapnumbermap)); | 3621 __ Branch(&call_runtime, ne, scratch, Operand(heapnumbermap)); |
3632 // Base is a heapnumber. Load it into double register. | 3622 |
3633 __ ldc1(double_base, FieldMemOperand(base, HeapNumber::kValueOffset)); | 3623 __ ldc1(double_base, FieldMemOperand(base, HeapNumber::kValueOffset)); |
3634 | 3624 __ jmp(&unpack_exponent); |
3635 __ bind(&convert_exponent); | 3625 |
| 3626 __ bind(&base_is_smi); |
| 3627 __ SmiUntag(base); |
| 3628 __ mtc1(base, single_scratch); |
| 3629 __ cvt_d_w(double_base, single_scratch); |
| 3630 __ bind(&unpack_exponent); |
| 3631 |
3636 __ JumpIfNotSmi(exponent, &exponent_not_smi); | 3632 __ JumpIfNotSmi(exponent, &exponent_not_smi); |
3637 __ SmiUntag(exponent); | 3633 __ SmiUntag(exponent); |
3638 | 3634 __ jmp(&int_exponent); |
3639 // The base is in a double register and the exponent is | |
3640 // an untagged smi. Allocate a heap number and call a | |
3641 // C function for integer exponents. The register containing | |
3642 // the heap number is callee-saved. | |
3643 __ AllocateHeapNumber(heapnumber, | |
3644 scratch, | |
3645 scratch2, | |
3646 heapnumbermap, | |
3647 &call_runtime); | |
3648 __ push(ra); | |
3649 __ PrepareCallCFunction(1, 1, scratch); | |
3650 __ SetCallCDoubleArguments(double_base, exponent); | |
3651 { | |
3652 AllowExternalCallThatCantCauseGC scope(masm); | |
3653 __ CallCFunction( | |
3654 ExternalReference::power_double_int_function(masm->isolate()), 1, 1); | |
3655 __ pop(ra); | |
3656 __ GetCFunctionDoubleResult(double_result); | |
3657 } | |
3658 __ sdc1(double_result, | |
3659 FieldMemOperand(heapnumber, HeapNumber::kValueOffset)); | |
3660 __ mov(v0, heapnumber); | |
3661 __ DropAndRet(2 * kPointerSize); | |
3662 | 3635 |
3663 __ bind(&exponent_not_smi); | 3636 __ bind(&exponent_not_smi); |
3664 __ lw(scratch, FieldMemOperand(exponent, JSObject::kMapOffset)); | 3637 __ lw(scratch, FieldMemOperand(exponent, JSObject::kMapOffset)); |
3665 __ Branch(&call_runtime, ne, scratch, Operand(heapnumbermap)); | 3638 __ Branch(&call_runtime, ne, scratch, Operand(heapnumbermap)); |
3666 // Exponent is a heapnumber. Load it into double register. | |
3667 __ ldc1(double_exponent, | 3639 __ ldc1(double_exponent, |
3668 FieldMemOperand(exponent, HeapNumber::kValueOffset)); | 3640 FieldMemOperand(exponent, HeapNumber::kValueOffset)); |
3669 | 3641 } else if (exponent_type_ == TAGGED) { |
3670 // The base and the exponent are in double registers. | 3642 // Base is already in double_base. |
3671 // Allocate a heap number and call a C function for | 3643 __ JumpIfNotSmi(exponent, &exponent_not_smi); |
3672 // double exponents. The register containing | 3644 __ SmiUntag(exponent); |
3673 // the heap number is callee-saved. | 3645 __ jmp(&int_exponent); |
3674 __ AllocateHeapNumber(heapnumber, | 3646 |
3675 scratch, | 3647 __ bind(&exponent_not_smi); |
3676 scratch2, | 3648 __ ldc1(double_exponent, |
3677 heapnumbermap, | 3649 FieldMemOperand(exponent, HeapNumber::kValueOffset)); |
3678 &call_runtime); | 3650 } |
| 3651 |
| 3652 if (exponent_type_ != INTEGER) { |
| 3653 Label int_exponent_convert; |
| 3654 // Detect integer exponents stored as double. |
| 3655 __ EmitFPUTruncate(kRoundToMinusInf, |
| 3656 single_scratch, |
| 3657 double_exponent, |
| 3658 scratch, |
| 3659 scratch2, |
| 3660 kCheckForInexactConversion); |
| 3661 // scratch2 == 0 means there was no conversion error. |
| 3662 __ Branch(&int_exponent_convert, eq, scratch2, Operand(zero_reg)); |
| 3663 |
| 3664 if (exponent_type_ == ON_STACK) { |
| 3665 // Detect square root case. Crankshaft detects constant +/-0.5 at |
| 3666 // compile time and uses DoMathPowHalf instead. We then skip this check |
| 3667 // for non-constant cases of +/-0.5 as these hardly occur. |
| 3668 Label not_plus_half; |
| 3669 |
| 3670 // Test for 0.5. |
| 3671 __ Move(double_scratch, 0.5); |
| 3672 __ BranchF(USE_DELAY_SLOT, |
| 3673 ¬_plus_half, |
| 3674 NULL, |
| 3675 ne, |
| 3676 double_exponent, |
| 3677 double_scratch); |
| 3678 |
| 3679 // Calculates square root of base. Check for the special case of |
| 3680 // Math.pow(-Infinity, 0.5) == Infinity (ECMA spec, 15.8.2.13). |
| 3681 __ Move(double_scratch, -V8_INFINITY); |
| 3682 __ BranchF(USE_DELAY_SLOT, &done, NULL, eq, double_base, double_scratch); |
| 3683 __ neg_d(double_result, double_scratch); |
| 3684 |
| 3685 // Add +0 to convert -0 to +0. |
| 3686 __ add_d(double_scratch, double_base, kDoubleRegZero); |
| 3687 __ sqrt_d(double_result, double_scratch); |
| 3688 __ jmp(&done); |
| 3689 |
| 3690 __ bind(¬_plus_half); |
| 3691 __ Move(double_scratch, -0.5); |
| 3692 __ BranchF(USE_DELAY_SLOT, |
| 3693 &call_runtime, |
| 3694 NULL, |
| 3695 ne, |
| 3696 double_exponent, |
| 3697 double_scratch); |
| 3698 |
| 3699 // Calculates square root of base. Check for the special case of |
| 3700 // Math.pow(-Infinity, -0.5) == 0 (ECMA spec, 15.8.2.13). |
| 3701 __ Move(double_scratch, -V8_INFINITY); |
| 3702 __ BranchF(USE_DELAY_SLOT, &done, NULL, eq, double_base, double_scratch); |
| 3703 __ Move(double_result, kDoubleRegZero); |
| 3704 |
| 3705 // Add +0 to convert -0 to +0. |
| 3706 __ add_d(double_scratch, double_base, kDoubleRegZero); |
| 3707 __ Move(double_result, 1); |
| 3708 __ sqrt_d(double_scratch, double_scratch); |
| 3709 __ div_d(double_result, double_result, double_scratch); |
| 3710 __ jmp(&done); |
| 3711 } |
| 3712 |
3679 __ push(ra); | 3713 __ push(ra); |
3680 __ PrepareCallCFunction(0, 2, scratch); | |
3681 // ABI (o32) for func(double a, double b): a in f12, b in f14. | |
3682 ASSERT(double_base.is(f12)); | |
3683 ASSERT(double_exponent.is(f14)); | |
3684 __ SetCallCDoubleArguments(double_base, double_exponent); | |
3685 { | 3714 { |
3686 AllowExternalCallThatCantCauseGC scope(masm); | 3715 AllowExternalCallThatCantCauseGC scope(masm); |
| 3716 __ PrepareCallCFunction(0, 2, scratch); |
| 3717 __ SetCallCDoubleArguments(double_base, double_exponent); |
3687 __ CallCFunction( | 3718 __ CallCFunction( |
3688 ExternalReference::power_double_double_function(masm->isolate()), | 3719 ExternalReference::power_double_double_function(masm->isolate()), |
3689 0, | 3720 0, 2); |
3690 2); | |
3691 __ pop(ra); | |
3692 __ GetCFunctionDoubleResult(double_result); | |
3693 } | 3721 } |
| 3722 __ pop(ra); |
| 3723 __ GetCFunctionDoubleResult(double_result); |
| 3724 __ jmp(&done); |
| 3725 |
| 3726 __ bind(&int_exponent_convert); |
| 3727 __ mfc1(exponent, single_scratch); |
| 3728 } |
| 3729 |
| 3730 // Calculate power with integer exponent. |
| 3731 __ bind(&int_exponent); |
| 3732 |
| 3733 __ mov(scratch, exponent); // Back up exponent. |
| 3734 __ mov_d(double_scratch, double_base); // Back up base. |
| 3735 __ Move(double_result, 1.0); |
| 3736 |
| 3737 // Get absolute value of exponent. |
| 3738 Label positive_exponent; |
| 3739 __ Branch(&positive_exponent, ge, scratch, Operand(zero_reg)); |
| 3740 __ Subu(scratch, zero_reg, scratch); |
| 3741 __ bind(&positive_exponent); |
| 3742 |
| 3743 Label while_true, no_carry, loop_end; |
| 3744 __ bind(&while_true); |
| 3745 |
| 3746 __ And(scratch2, scratch, 1); |
| 3747 |
| 3748 __ Branch(&no_carry, eq, scratch2, Operand(zero_reg)); |
| 3749 __ mul_d(double_result, double_result, double_scratch); |
| 3750 __ bind(&no_carry); |
| 3751 |
| 3752 __ sra(scratch, scratch, 1); |
| 3753 |
| 3754 __ Branch(&loop_end, eq, scratch, Operand(zero_reg)); |
| 3755 __ mul_d(double_scratch, double_scratch, double_scratch); |
| 3756 |
| 3757 __ Branch(&while_true); |
| 3758 |
| 3759 __ bind(&loop_end); |
| 3760 |
| 3761 __ Branch(&done, ge, exponent, Operand(zero_reg)); |
| 3762 __ Move(double_scratch, 1.0); |
| 3763 __ div_d(double_result, double_scratch, double_result); |
| 3764 // Test whether result is zero. Bail out to check for subnormal result. |
| 3765 // Due to subnormals, x^-y == (1/x)^y does not hold in all cases. |
| 3766 __ BranchF(&done, NULL, ne, double_result, kDoubleRegZero); |
| 3767 |
| 3768 // double_exponent may not contain the exponent value if the input was a |
| 3769 // smi. We set it with exponent value before bailing out. |
| 3770 __ mtc1(exponent, single_scratch); |
| 3771 __ cvt_d_w(double_exponent, single_scratch); |
| 3772 |
| 3773 // Returning or bailing out. |
| 3774 Counters* counters = masm->isolate()->counters(); |
| 3775 if (exponent_type_ == ON_STACK) { |
| 3776 // The arguments are still on the stack. |
| 3777 __ bind(&call_runtime); |
| 3778 __ TailCallRuntime(Runtime::kMath_pow_cfunction, 2, 1); |
| 3779 |
| 3780 // The stub is called from non-optimized code, which expects the result |
| 3781 // as heap number in exponent. |
| 3782 __ bind(&done); |
| 3783 __ AllocateHeapNumber( |
| 3784 heapnumber, scratch, scratch2, heapnumbermap, &call_runtime); |
3694 __ sdc1(double_result, | 3785 __ sdc1(double_result, |
3695 FieldMemOperand(heapnumber, HeapNumber::kValueOffset)); | 3786 FieldMemOperand(heapnumber, HeapNumber::kValueOffset)); |
3696 __ mov(v0, heapnumber); | 3787 ASSERT(heapnumber.is(v0)); |
3697 __ DropAndRet(2 * kPointerSize); | 3788 __ IncrementCounter(counters->math_pow(), 1, scratch, scratch2); |
| 3789 __ DropAndRet(2); |
| 3790 } else { |
| 3791 __ push(ra); |
| 3792 { |
| 3793 AllowExternalCallThatCantCauseGC scope(masm); |
| 3794 __ PrepareCallCFunction(0, 2, scratch); |
| 3795 __ SetCallCDoubleArguments(double_base, double_exponent); |
| 3796 __ CallCFunction( |
| 3797 ExternalReference::power_double_double_function(masm->isolate()), |
| 3798 0, 2); |
| 3799 } |
| 3800 __ pop(ra); |
| 3801 __ GetCFunctionDoubleResult(double_result); |
| 3802 |
| 3803 __ bind(&done); |
| 3804 __ IncrementCounter(counters->math_pow(), 1, scratch, scratch2); |
| 3805 __ Ret(); |
3698 } | 3806 } |
3699 | |
3700 __ bind(&call_runtime); | |
3701 __ TailCallRuntime(Runtime::kMath_pow_cfunction, 2, 1); | |
3702 } | 3807 } |
3703 | 3808 |
3704 | 3809 |
3705 bool CEntryStub::NeedsImmovableCode() { | 3810 bool CEntryStub::NeedsImmovableCode() { |
3706 return true; | 3811 return true; |
3707 } | 3812 } |
3708 | 3813 |
3709 | 3814 |
3710 bool CEntryStub::IsPregenerated() { | 3815 bool CEntryStub::IsPregenerated() { |
3711 return (!save_doubles_ || ISOLATE->fp_stubs_generated()) && | 3816 return (!save_doubles_ || ISOLATE->fp_stubs_generated()) && |
(...skipping 3820 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7532 __ Ret(USE_DELAY_SLOT); | 7637 __ Ret(USE_DELAY_SLOT); |
7533 __ mov(v0, a0); | 7638 __ mov(v0, a0); |
7534 } | 7639 } |
7535 | 7640 |
7536 | 7641 |
7537 #undef __ | 7642 #undef __ |
7538 | 7643 |
7539 } } // namespace v8::internal | 7644 } } // namespace v8::internal |
7540 | 7645 |
7541 #endif // V8_TARGET_ARCH_MIPS | 7646 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |