| OLD | NEW | 
|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #if V8_TARGET_ARCH_MIPS64 | 5 #if V8_TARGET_ARCH_MIPS64 | 
| 6 | 6 | 
| 7 #include "src/code-stubs.h" | 7 #include "src/code-stubs.h" | 
| 8 #include "src/api-arguments.h" | 8 #include "src/api-arguments.h" | 
| 9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" | 
| 10 #include "src/codegen.h" | 10 #include "src/codegen.h" | 
| (...skipping 739 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 750   if (save_doubles()) { | 750   if (save_doubles()) { | 
| 751     __ MultiPopFPU(kCallerSavedFPU); | 751     __ MultiPopFPU(kCallerSavedFPU); | 
| 752   } | 752   } | 
| 753 | 753 | 
| 754   __ MultiPop(kJSCallerSaved | ra.bit()); | 754   __ MultiPop(kJSCallerSaved | ra.bit()); | 
| 755   __ Ret(); | 755   __ Ret(); | 
| 756 } | 756 } | 
| 757 | 757 | 
| 758 | 758 | 
| 759 void MathPowStub::Generate(MacroAssembler* masm) { | 759 void MathPowStub::Generate(MacroAssembler* masm) { | 
| 760   const Register base = a1; |  | 
| 761   const Register exponent = MathPowTaggedDescriptor::exponent(); | 760   const Register exponent = MathPowTaggedDescriptor::exponent(); | 
| 762   DCHECK(exponent.is(a2)); | 761   DCHECK(exponent.is(a2)); | 
| 763   const Register heapnumbermap = a5; |  | 
| 764   const Register heapnumber = v0; |  | 
| 765   const DoubleRegister double_base = f2; | 762   const DoubleRegister double_base = f2; | 
| 766   const DoubleRegister double_exponent = f4; | 763   const DoubleRegister double_exponent = f4; | 
| 767   const DoubleRegister double_result = f0; | 764   const DoubleRegister double_result = f0; | 
| 768   const DoubleRegister double_scratch = f6; | 765   const DoubleRegister double_scratch = f6; | 
| 769   const FPURegister single_scratch = f8; | 766   const FPURegister single_scratch = f8; | 
| 770   const Register scratch = t1; | 767   const Register scratch = t1; | 
| 771   const Register scratch2 = a7; | 768   const Register scratch2 = a7; | 
| 772 | 769 | 
| 773   Label call_runtime, done, int_exponent; | 770   Label call_runtime, done, int_exponent; | 
| 774   if (exponent_type() == ON_STACK) { | 771   if (exponent_type() == TAGGED) { | 
| 775     Label base_is_smi, unpack_exponent; |  | 
| 776     // The exponent and base are supplied as arguments on the stack. |  | 
| 777     // This can only happen if the stub is called from non-optimized code. |  | 
| 778     // Load input parameters from stack to double registers. |  | 
| 779     __ ld(base, MemOperand(sp, 1 * kPointerSize)); |  | 
| 780     __ ld(exponent, MemOperand(sp, 0 * kPointerSize)); |  | 
| 781 |  | 
| 782     __ LoadRoot(heapnumbermap, Heap::kHeapNumberMapRootIndex); |  | 
| 783 |  | 
| 784     __ UntagAndJumpIfSmi(scratch, base, &base_is_smi); |  | 
| 785     __ ld(scratch, FieldMemOperand(base, JSObject::kMapOffset)); |  | 
| 786     __ Branch(&call_runtime, ne, scratch, Operand(heapnumbermap)); |  | 
| 787 |  | 
| 788     __ ldc1(double_base, FieldMemOperand(base, HeapNumber::kValueOffset)); |  | 
| 789     __ jmp(&unpack_exponent); |  | 
| 790 |  | 
| 791     __ bind(&base_is_smi); |  | 
| 792     __ mtc1(scratch, single_scratch); |  | 
| 793     __ cvt_d_w(double_base, single_scratch); |  | 
| 794     __ bind(&unpack_exponent); |  | 
| 795 |  | 
| 796     __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent); |  | 
| 797 |  | 
| 798     __ ld(scratch, FieldMemOperand(exponent, JSObject::kMapOffset)); |  | 
| 799     __ Branch(&call_runtime, ne, scratch, Operand(heapnumbermap)); |  | 
| 800     __ ldc1(double_exponent, |  | 
| 801             FieldMemOperand(exponent, HeapNumber::kValueOffset)); |  | 
| 802   } else if (exponent_type() == TAGGED) { |  | 
| 803     // Base is already in double_base. | 772     // Base is already in double_base. | 
| 804     __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent); | 773     __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent); | 
| 805 | 774 | 
| 806     __ ldc1(double_exponent, | 775     __ ldc1(double_exponent, | 
| 807             FieldMemOperand(exponent, HeapNumber::kValueOffset)); | 776             FieldMemOperand(exponent, HeapNumber::kValueOffset)); | 
| 808   } | 777   } | 
| 809 | 778 | 
| 810   if (exponent_type() != INTEGER) { | 779   if (exponent_type() != INTEGER) { | 
| 811     Label int_exponent_convert; | 780     Label int_exponent_convert; | 
| 812     // Detect integer exponents stored as double. | 781     // Detect integer exponents stored as double. | 
| 813     __ EmitFPUTruncate(kRoundToMinusInf, | 782     __ EmitFPUTruncate(kRoundToMinusInf, | 
| 814                        scratch, | 783                        scratch, | 
| 815                        double_exponent, | 784                        double_exponent, | 
| 816                        at, | 785                        at, | 
| 817                        double_scratch, | 786                        double_scratch, | 
| 818                        scratch2, | 787                        scratch2, | 
| 819                        kCheckForInexactConversion); | 788                        kCheckForInexactConversion); | 
| 820     // scratch2 == 0 means there was no conversion error. | 789     // scratch2 == 0 means there was no conversion error. | 
| 821     __ Branch(&int_exponent_convert, eq, scratch2, Operand(zero_reg)); | 790     __ Branch(&int_exponent_convert, eq, scratch2, Operand(zero_reg)); | 
| 822 | 791 | 
| 823     if (exponent_type() == ON_STACK) { |  | 
| 824       // Detect square root case.  Crankshaft detects constant +/-0.5 at |  | 
| 825       // compile time and uses DoMathPowHalf instead.  We then skip this check |  | 
| 826       // for non-constant cases of +/-0.5 as these hardly occur. |  | 
| 827       Label not_plus_half; |  | 
| 828 |  | 
| 829       // Test for 0.5. |  | 
| 830       __ Move(double_scratch, 0.5); |  | 
| 831       __ BranchF(USE_DELAY_SLOT, |  | 
| 832                  ¬_plus_half, |  | 
| 833                  NULL, |  | 
| 834                  ne, |  | 
| 835                  double_exponent, |  | 
| 836                  double_scratch); |  | 
| 837       // double_scratch can be overwritten in the delay slot. |  | 
| 838       // Calculates square root of base.  Check for the special case of |  | 
| 839       // Math.pow(-Infinity, 0.5) == Infinity (ECMA spec, 15.8.2.13). |  | 
| 840       __ Move(double_scratch, static_cast<double>(-V8_INFINITY)); |  | 
| 841       __ BranchF(USE_DELAY_SLOT, &done, NULL, eq, double_base, double_scratch); |  | 
| 842       __ neg_d(double_result, double_scratch); |  | 
| 843 |  | 
| 844       // Add +0 to convert -0 to +0. |  | 
| 845       __ add_d(double_scratch, double_base, kDoubleRegZero); |  | 
| 846       __ sqrt_d(double_result, double_scratch); |  | 
| 847       __ jmp(&done); |  | 
| 848 |  | 
| 849       __ bind(¬_plus_half); |  | 
| 850       __ Move(double_scratch, -0.5); |  | 
| 851       __ BranchF(USE_DELAY_SLOT, |  | 
| 852                  &call_runtime, |  | 
| 853                  NULL, |  | 
| 854                  ne, |  | 
| 855                  double_exponent, |  | 
| 856                  double_scratch); |  | 
| 857       // double_scratch can be overwritten in the delay slot. |  | 
| 858       // Calculates square root of base.  Check for the special case of |  | 
| 859       // Math.pow(-Infinity, -0.5) == 0 (ECMA spec, 15.8.2.13). |  | 
| 860       __ Move(double_scratch, static_cast<double>(-V8_INFINITY)); |  | 
| 861       __ BranchF(USE_DELAY_SLOT, &done, NULL, eq, double_base, double_scratch); |  | 
| 862       __ Move(double_result, kDoubleRegZero); |  | 
| 863 |  | 
| 864       // Add +0 to convert -0 to +0. |  | 
| 865       __ add_d(double_scratch, double_base, kDoubleRegZero); |  | 
| 866       __ Move(double_result, 1.); |  | 
| 867       __ sqrt_d(double_scratch, double_scratch); |  | 
| 868       __ div_d(double_result, double_result, double_scratch); |  | 
| 869       __ jmp(&done); |  | 
| 870     } |  | 
| 871 |  | 
| 872     __ push(ra); | 792     __ push(ra); | 
| 873     { | 793     { | 
| 874       AllowExternalCallThatCantCauseGC scope(masm); | 794       AllowExternalCallThatCantCauseGC scope(masm); | 
| 875       __ PrepareCallCFunction(0, 2, scratch2); | 795       __ PrepareCallCFunction(0, 2, scratch2); | 
| 876       __ MovToFloatParameters(double_base, double_exponent); | 796       __ MovToFloatParameters(double_base, double_exponent); | 
| 877       __ CallCFunction( | 797       __ CallCFunction( | 
| 878           ExternalReference::power_double_double_function(isolate()), | 798           ExternalReference::power_double_double_function(isolate()), | 
| 879           0, 2); | 799           0, 2); | 
| 880     } | 800     } | 
| 881     __ pop(ra); | 801     __ pop(ra); | 
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 929   // Test whether result is zero.  Bail out to check for subnormal result. | 849   // Test whether result is zero.  Bail out to check for subnormal result. | 
| 930   // Due to subnormals, x^-y == (1/x)^y does not hold in all cases. | 850   // Due to subnormals, x^-y == (1/x)^y does not hold in all cases. | 
| 931   __ BranchF(&done, NULL, ne, double_result, kDoubleRegZero); | 851   __ BranchF(&done, NULL, ne, double_result, kDoubleRegZero); | 
| 932 | 852 | 
| 933   // double_exponent may not contain the exponent value if the input was a | 853   // double_exponent may not contain the exponent value if the input was a | 
| 934   // smi.  We set it with exponent value before bailing out. | 854   // smi.  We set it with exponent value before bailing out. | 
| 935   __ mtc1(exponent, single_scratch); | 855   __ mtc1(exponent, single_scratch); | 
| 936   __ cvt_d_w(double_exponent, single_scratch); | 856   __ cvt_d_w(double_exponent, single_scratch); | 
| 937 | 857 | 
| 938   // Returning or bailing out. | 858   // Returning or bailing out. | 
| 939   if (exponent_type() == ON_STACK) { | 859   __ push(ra); | 
| 940     // The arguments are still on the stack. | 860   { | 
| 941     __ bind(&call_runtime); | 861     AllowExternalCallThatCantCauseGC scope(masm); | 
| 942     __ TailCallRuntime(Runtime::kMathPowRT); | 862     __ PrepareCallCFunction(0, 2, scratch); | 
|  | 863     __ MovToFloatParameters(double_base, double_exponent); | 
|  | 864     __ CallCFunction(ExternalReference::power_double_double_function(isolate()), | 
|  | 865                      0, 2); | 
|  | 866   } | 
|  | 867   __ pop(ra); | 
|  | 868   __ MovFromFloatResult(double_result); | 
| 943 | 869 | 
| 944     // The stub is called from non-optimized code, which expects the result | 870   __ bind(&done); | 
| 945     // as heap number in exponent. | 871   __ Ret(); | 
| 946     __ bind(&done); |  | 
| 947     __ AllocateHeapNumber( |  | 
| 948         heapnumber, scratch, scratch2, heapnumbermap, &call_runtime); |  | 
| 949     __ sdc1(double_result, |  | 
| 950             FieldMemOperand(heapnumber, HeapNumber::kValueOffset)); |  | 
| 951     DCHECK(heapnumber.is(v0)); |  | 
| 952     __ DropAndRet(2); |  | 
| 953   } else { |  | 
| 954     __ push(ra); |  | 
| 955     { |  | 
| 956       AllowExternalCallThatCantCauseGC scope(masm); |  | 
| 957       __ PrepareCallCFunction(0, 2, scratch); |  | 
| 958       __ MovToFloatParameters(double_base, double_exponent); |  | 
| 959       __ CallCFunction( |  | 
| 960           ExternalReference::power_double_double_function(isolate()), |  | 
| 961           0, 2); |  | 
| 962     } |  | 
| 963     __ pop(ra); |  | 
| 964     __ MovFromFloatResult(double_result); |  | 
| 965 |  | 
| 966     __ bind(&done); |  | 
| 967     __ Ret(); |  | 
| 968   } |  | 
| 969 } | 872 } | 
| 970 | 873 | 
| 971 |  | 
| 972 bool CEntryStub::NeedsImmovableCode() { | 874 bool CEntryStub::NeedsImmovableCode() { | 
| 973   return true; | 875   return true; | 
| 974 } | 876 } | 
| 975 | 877 | 
| 976 | 878 | 
| 977 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { | 879 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { | 
| 978   CEntryStub::GenerateAheadOfTime(isolate); | 880   CEntryStub::GenerateAheadOfTime(isolate); | 
| 979   StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); | 881   StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); | 
| 980   StubFailureTrampolineStub::GenerateAheadOfTime(isolate); | 882   StubFailureTrampolineStub::GenerateAheadOfTime(isolate); | 
| 981   CommonArrayConstructorStub::GenerateStubsAheadOfTime(isolate); | 883   CommonArrayConstructorStub::GenerateStubsAheadOfTime(isolate); | 
| (...skipping 4568 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 5550                            kStackUnwindSpace, kInvalidStackOffset, | 5452                            kStackUnwindSpace, kInvalidStackOffset, | 
| 5551                            return_value_operand, NULL); | 5453                            return_value_operand, NULL); | 
| 5552 } | 5454 } | 
| 5553 | 5455 | 
| 5554 #undef __ | 5456 #undef __ | 
| 5555 | 5457 | 
| 5556 }  // namespace internal | 5458 }  // namespace internal | 
| 5557 }  // namespace v8 | 5459 }  // namespace v8 | 
| 5558 | 5460 | 
| 5559 #endif  // V8_TARGET_ARCH_MIPS64 | 5461 #endif  // V8_TARGET_ARCH_MIPS64 | 
| OLD | NEW | 
|---|