| 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 436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 447 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) { | 447 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) { |
| 448 // We don't allow a GC during a store buffer overflow so there is no need to | 448 // We don't allow a GC during a store buffer overflow so there is no need to |
| 449 // store the registers in any particular way, but we do have to store and | 449 // store the registers in any particular way, but we do have to store and |
| 450 // restore them. | 450 // restore them. |
| 451 __ pushad(); | 451 __ pushad(); |
| 452 if (save_doubles_ == kSaveFPRegs) { | 452 if (save_doubles_ == kSaveFPRegs) { |
| 453 CpuFeatureScope scope(masm, SSE2); | 453 CpuFeatureScope scope(masm, SSE2); |
| 454 __ sub(esp, Immediate(kDoubleSize * XMMRegister::kNumRegisters)); | 454 __ sub(esp, Immediate(kDoubleSize * XMMRegister::kNumRegisters)); |
| 455 for (int i = 0; i < XMMRegister::kNumRegisters; i++) { | 455 for (int i = 0; i < XMMRegister::kNumRegisters; i++) { |
| 456 XMMRegister reg = XMMRegister::from_code(i); | 456 XMMRegister reg = XMMRegister::from_code(i); |
| 457 __ movdbl(Operand(esp, i * kDoubleSize), reg); | 457 __ movsd(Operand(esp, i * kDoubleSize), reg); |
| 458 } | 458 } |
| 459 } | 459 } |
| 460 const int argument_count = 1; | 460 const int argument_count = 1; |
| 461 | 461 |
| 462 AllowExternalCallThatCantCauseGC scope(masm); | 462 AllowExternalCallThatCantCauseGC scope(masm); |
| 463 __ PrepareCallCFunction(argument_count, ecx); | 463 __ PrepareCallCFunction(argument_count, ecx); |
| 464 __ mov(Operand(esp, 0 * kPointerSize), | 464 __ mov(Operand(esp, 0 * kPointerSize), |
| 465 Immediate(ExternalReference::isolate_address(masm->isolate()))); | 465 Immediate(ExternalReference::isolate_address(masm->isolate()))); |
| 466 __ CallCFunction( | 466 __ CallCFunction( |
| 467 ExternalReference::store_buffer_overflow_function(masm->isolate()), | 467 ExternalReference::store_buffer_overflow_function(masm->isolate()), |
| 468 argument_count); | 468 argument_count); |
| 469 if (save_doubles_ == kSaveFPRegs) { | 469 if (save_doubles_ == kSaveFPRegs) { |
| 470 CpuFeatureScope scope(masm, SSE2); | 470 CpuFeatureScope scope(masm, SSE2); |
| 471 for (int i = 0; i < XMMRegister::kNumRegisters; i++) { | 471 for (int i = 0; i < XMMRegister::kNumRegisters; i++) { |
| 472 XMMRegister reg = XMMRegister::from_code(i); | 472 XMMRegister reg = XMMRegister::from_code(i); |
| 473 __ movdbl(reg, Operand(esp, i * kDoubleSize)); | 473 __ movsd(reg, Operand(esp, i * kDoubleSize)); |
| 474 } | 474 } |
| 475 __ add(esp, Immediate(kDoubleSize * XMMRegister::kNumRegisters)); | 475 __ add(esp, Immediate(kDoubleSize * XMMRegister::kNumRegisters)); |
| 476 } | 476 } |
| 477 __ popad(); | 477 __ popad(); |
| 478 __ ret(0); | 478 __ ret(0); |
| 479 } | 479 } |
| 480 | 480 |
| 481 | 481 |
| 482 class FloatingPointHelper : public AllStatic { | 482 class FloatingPointHelper : public AllStatic { |
| 483 public: | 483 public: |
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 763 __ j(not_equal, &cache_miss, Label::kNear); | 763 __ j(not_equal, &cache_miss, Label::kNear); |
| 764 // Cache hit! | 764 // Cache hit! |
| 765 Counters* counters = masm->isolate()->counters(); | 765 Counters* counters = masm->isolate()->counters(); |
| 766 __ IncrementCounter(counters->transcendental_cache_hit(), 1); | 766 __ IncrementCounter(counters->transcendental_cache_hit(), 1); |
| 767 __ mov(eax, Operand(ecx, 2 * kIntSize)); | 767 __ mov(eax, Operand(ecx, 2 * kIntSize)); |
| 768 if (tagged) { | 768 if (tagged) { |
| 769 __ fstp(0); | 769 __ fstp(0); |
| 770 __ ret(kPointerSize); | 770 __ ret(kPointerSize); |
| 771 } else { // UNTAGGED. | 771 } else { // UNTAGGED. |
| 772 CpuFeatureScope scope(masm, SSE2); | 772 CpuFeatureScope scope(masm, SSE2); |
| 773 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); | 773 __ movsd(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); |
| 774 __ Ret(); | 774 __ Ret(); |
| 775 } | 775 } |
| 776 | 776 |
| 777 __ bind(&cache_miss); | 777 __ bind(&cache_miss); |
| 778 __ IncrementCounter(counters->transcendental_cache_miss(), 1); | 778 __ IncrementCounter(counters->transcendental_cache_miss(), 1); |
| 779 // Update cache with new value. | 779 // Update cache with new value. |
| 780 // We are short on registers, so use no_reg as scratch. | 780 // We are short on registers, so use no_reg as scratch. |
| 781 // This gives slightly larger code. | 781 // This gives slightly larger code. |
| 782 if (tagged) { | 782 if (tagged) { |
| 783 __ AllocateHeapNumber(eax, edi, no_reg, &runtime_call_clear_stack); | 783 __ AllocateHeapNumber(eax, edi, no_reg, &runtime_call_clear_stack); |
| 784 } else { // UNTAGGED. | 784 } else { // UNTAGGED. |
| 785 CpuFeatureScope scope(masm, SSE2); | 785 CpuFeatureScope scope(masm, SSE2); |
| 786 __ AllocateHeapNumber(eax, edi, no_reg, &skip_cache); | 786 __ AllocateHeapNumber(eax, edi, no_reg, &skip_cache); |
| 787 __ sub(esp, Immediate(kDoubleSize)); | 787 __ sub(esp, Immediate(kDoubleSize)); |
| 788 __ movdbl(Operand(esp, 0), xmm1); | 788 __ movsd(Operand(esp, 0), xmm1); |
| 789 __ fld_d(Operand(esp, 0)); | 789 __ fld_d(Operand(esp, 0)); |
| 790 __ add(esp, Immediate(kDoubleSize)); | 790 __ add(esp, Immediate(kDoubleSize)); |
| 791 } | 791 } |
| 792 GenerateOperation(masm, type_); | 792 GenerateOperation(masm, type_); |
| 793 __ mov(Operand(ecx, 0), ebx); | 793 __ mov(Operand(ecx, 0), ebx); |
| 794 __ mov(Operand(ecx, kIntSize), edx); | 794 __ mov(Operand(ecx, kIntSize), edx); |
| 795 __ mov(Operand(ecx, 2 * kIntSize), eax); | 795 __ mov(Operand(ecx, 2 * kIntSize), eax); |
| 796 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 796 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
| 797 if (tagged) { | 797 if (tagged) { |
| 798 __ ret(kPointerSize); | 798 __ ret(kPointerSize); |
| 799 } else { // UNTAGGED. | 799 } else { // UNTAGGED. |
| 800 CpuFeatureScope scope(masm, SSE2); | 800 CpuFeatureScope scope(masm, SSE2); |
| 801 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); | 801 __ movsd(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); |
| 802 __ Ret(); | 802 __ Ret(); |
| 803 | 803 |
| 804 // Skip cache and return answer directly, only in untagged case. | 804 // Skip cache and return answer directly, only in untagged case. |
| 805 __ bind(&skip_cache); | 805 __ bind(&skip_cache); |
| 806 __ sub(esp, Immediate(kDoubleSize)); | 806 __ sub(esp, Immediate(kDoubleSize)); |
| 807 __ movdbl(Operand(esp, 0), xmm1); | 807 __ movsd(Operand(esp, 0), xmm1); |
| 808 __ fld_d(Operand(esp, 0)); | 808 __ fld_d(Operand(esp, 0)); |
| 809 GenerateOperation(masm, type_); | 809 GenerateOperation(masm, type_); |
| 810 __ fstp_d(Operand(esp, 0)); | 810 __ fstp_d(Operand(esp, 0)); |
| 811 __ movdbl(xmm1, Operand(esp, 0)); | 811 __ movsd(xmm1, Operand(esp, 0)); |
| 812 __ add(esp, Immediate(kDoubleSize)); | 812 __ add(esp, Immediate(kDoubleSize)); |
| 813 // We return the value in xmm1 without adding it to the cache, but | 813 // We return the value in xmm1 without adding it to the cache, but |
| 814 // we cause a scavenging GC so that future allocations will succeed. | 814 // we cause a scavenging GC so that future allocations will succeed. |
| 815 { | 815 { |
| 816 FrameScope scope(masm, StackFrame::INTERNAL); | 816 FrameScope scope(masm, StackFrame::INTERNAL); |
| 817 // Allocate an unused object bigger than a HeapNumber. | 817 // Allocate an unused object bigger than a HeapNumber. |
| 818 __ push(Immediate(Smi::FromInt(2 * kDoubleSize))); | 818 __ push(Immediate(Smi::FromInt(2 * kDoubleSize))); |
| 819 __ CallRuntimeSaveDoubles(Runtime::kAllocateInNewSpace); | 819 __ CallRuntimeSaveDoubles(Runtime::kAllocateInNewSpace); |
| 820 } | 820 } |
| 821 __ Ret(); | 821 __ Ret(); |
| 822 } | 822 } |
| 823 | 823 |
| 824 // Call runtime, doing whatever allocation and cleanup is necessary. | 824 // Call runtime, doing whatever allocation and cleanup is necessary. |
| 825 if (tagged) { | 825 if (tagged) { |
| 826 __ bind(&runtime_call_clear_stack); | 826 __ bind(&runtime_call_clear_stack); |
| 827 __ fstp(0); | 827 __ fstp(0); |
| 828 __ bind(&runtime_call); | 828 __ bind(&runtime_call); |
| 829 ExternalReference runtime = | 829 ExternalReference runtime = |
| 830 ExternalReference(RuntimeFunction(), masm->isolate()); | 830 ExternalReference(RuntimeFunction(), masm->isolate()); |
| 831 __ TailCallExternalReference(runtime, 1, 1); | 831 __ TailCallExternalReference(runtime, 1, 1); |
| 832 } else { // UNTAGGED. | 832 } else { // UNTAGGED. |
| 833 CpuFeatureScope scope(masm, SSE2); | 833 CpuFeatureScope scope(masm, SSE2); |
| 834 __ bind(&runtime_call_clear_stack); | 834 __ bind(&runtime_call_clear_stack); |
| 835 __ bind(&runtime_call); | 835 __ bind(&runtime_call); |
| 836 __ AllocateHeapNumber(eax, edi, no_reg, &skip_cache); | 836 __ AllocateHeapNumber(eax, edi, no_reg, &skip_cache); |
| 837 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm1); | 837 __ movsd(FieldOperand(eax, HeapNumber::kValueOffset), xmm1); |
| 838 { | 838 { |
| 839 FrameScope scope(masm, StackFrame::INTERNAL); | 839 FrameScope scope(masm, StackFrame::INTERNAL); |
| 840 __ push(eax); | 840 __ push(eax); |
| 841 __ CallRuntime(RuntimeFunction(), 1); | 841 __ CallRuntime(RuntimeFunction(), 1); |
| 842 } | 842 } |
| 843 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); | 843 __ movsd(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); |
| 844 __ Ret(); | 844 __ Ret(); |
| 845 } | 845 } |
| 846 } | 846 } |
| 847 | 847 |
| 848 | 848 |
| 849 Runtime::FunctionId TranscendentalCacheStub::RuntimeFunction() { | 849 Runtime::FunctionId TranscendentalCacheStub::RuntimeFunction() { |
| 850 switch (type_) { | 850 switch (type_) { |
| 851 case TranscendentalCache::SIN: return Runtime::kMath_sin; | 851 case TranscendentalCache::SIN: return Runtime::kMath_sin; |
| 852 case TranscendentalCache::COS: return Runtime::kMath_cos; | 852 case TranscendentalCache::COS: return Runtime::kMath_cos; |
| 853 case TranscendentalCache::TAN: return Runtime::kMath_tan; | 853 case TranscendentalCache::TAN: return Runtime::kMath_tan; |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 976 | 976 |
| 977 | 977 |
| 978 void FloatingPointHelper::LoadSSE2Operands(MacroAssembler* masm, | 978 void FloatingPointHelper::LoadSSE2Operands(MacroAssembler* masm, |
| 979 Label* not_numbers) { | 979 Label* not_numbers) { |
| 980 Label load_smi_edx, load_eax, load_smi_eax, load_float_eax, done; | 980 Label load_smi_edx, load_eax, load_smi_eax, load_float_eax, done; |
| 981 // Load operand in edx into xmm0, or branch to not_numbers. | 981 // Load operand in edx into xmm0, or branch to not_numbers. |
| 982 __ JumpIfSmi(edx, &load_smi_edx, Label::kNear); | 982 __ JumpIfSmi(edx, &load_smi_edx, Label::kNear); |
| 983 Factory* factory = masm->isolate()->factory(); | 983 Factory* factory = masm->isolate()->factory(); |
| 984 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), factory->heap_number_map()); | 984 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), factory->heap_number_map()); |
| 985 __ j(not_equal, not_numbers); // Argument in edx is not a number. | 985 __ j(not_equal, not_numbers); // Argument in edx is not a number. |
| 986 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); | 986 __ movsd(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); |
| 987 __ bind(&load_eax); | 987 __ bind(&load_eax); |
| 988 // Load operand in eax into xmm1, or branch to not_numbers. | 988 // Load operand in eax into xmm1, or branch to not_numbers. |
| 989 __ JumpIfSmi(eax, &load_smi_eax, Label::kNear); | 989 __ JumpIfSmi(eax, &load_smi_eax, Label::kNear); |
| 990 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), factory->heap_number_map()); | 990 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), factory->heap_number_map()); |
| 991 __ j(equal, &load_float_eax, Label::kNear); | 991 __ j(equal, &load_float_eax, Label::kNear); |
| 992 __ jmp(not_numbers); // Argument in eax is not a number. | 992 __ jmp(not_numbers); // Argument in eax is not a number. |
| 993 __ bind(&load_smi_edx); | 993 __ bind(&load_smi_edx); |
| 994 __ SmiUntag(edx); // Untag smi before converting to float. | 994 __ SmiUntag(edx); // Untag smi before converting to float. |
| 995 __ Cvtsi2sd(xmm0, edx); | 995 __ Cvtsi2sd(xmm0, edx); |
| 996 __ SmiTag(edx); // Retag smi for heap number overwriting test. | 996 __ SmiTag(edx); // Retag smi for heap number overwriting test. |
| 997 __ jmp(&load_eax); | 997 __ jmp(&load_eax); |
| 998 __ bind(&load_smi_eax); | 998 __ bind(&load_smi_eax); |
| 999 __ SmiUntag(eax); // Untag smi before converting to float. | 999 __ SmiUntag(eax); // Untag smi before converting to float. |
| 1000 __ Cvtsi2sd(xmm1, eax); | 1000 __ Cvtsi2sd(xmm1, eax); |
| 1001 __ SmiTag(eax); // Retag smi for heap number overwriting test. | 1001 __ SmiTag(eax); // Retag smi for heap number overwriting test. |
| 1002 __ jmp(&done, Label::kNear); | 1002 __ jmp(&done, Label::kNear); |
| 1003 __ bind(&load_float_eax); | 1003 __ bind(&load_float_eax); |
| 1004 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); | 1004 __ movsd(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); |
| 1005 __ bind(&done); | 1005 __ bind(&done); |
| 1006 } | 1006 } |
| 1007 | 1007 |
| 1008 | 1008 |
| 1009 void FloatingPointHelper::CheckFloatOperands(MacroAssembler* masm, | 1009 void FloatingPointHelper::CheckFloatOperands(MacroAssembler* masm, |
| 1010 Label* non_float, | 1010 Label* non_float, |
| 1011 Register scratch) { | 1011 Register scratch) { |
| 1012 Label test_other, done; | 1012 Label test_other, done; |
| 1013 // Test if both operands are floats or smi -> scratch=k_is_float; | 1013 // Test if both operands are floats or smi -> scratch=k_is_float; |
| 1014 // Otherwise scratch = k_not_float. | 1014 // Otherwise scratch = k_not_float. |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1052 // This can only happen if the stub is called from non-optimized code. | 1052 // This can only happen if the stub is called from non-optimized code. |
| 1053 // Load input parameters from stack. | 1053 // Load input parameters from stack. |
| 1054 __ mov(base, Operand(esp, 2 * kPointerSize)); | 1054 __ mov(base, Operand(esp, 2 * kPointerSize)); |
| 1055 __ mov(exponent, Operand(esp, 1 * kPointerSize)); | 1055 __ mov(exponent, Operand(esp, 1 * kPointerSize)); |
| 1056 | 1056 |
| 1057 __ JumpIfSmi(base, &base_is_smi, Label::kNear); | 1057 __ JumpIfSmi(base, &base_is_smi, Label::kNear); |
| 1058 __ cmp(FieldOperand(base, HeapObject::kMapOffset), | 1058 __ cmp(FieldOperand(base, HeapObject::kMapOffset), |
| 1059 factory->heap_number_map()); | 1059 factory->heap_number_map()); |
| 1060 __ j(not_equal, &call_runtime); | 1060 __ j(not_equal, &call_runtime); |
| 1061 | 1061 |
| 1062 __ movdbl(double_base, FieldOperand(base, HeapNumber::kValueOffset)); | 1062 __ movsd(double_base, FieldOperand(base, HeapNumber::kValueOffset)); |
| 1063 __ jmp(&unpack_exponent, Label::kNear); | 1063 __ jmp(&unpack_exponent, Label::kNear); |
| 1064 | 1064 |
| 1065 __ bind(&base_is_smi); | 1065 __ bind(&base_is_smi); |
| 1066 __ SmiUntag(base); | 1066 __ SmiUntag(base); |
| 1067 __ Cvtsi2sd(double_base, base); | 1067 __ Cvtsi2sd(double_base, base); |
| 1068 | 1068 |
| 1069 __ bind(&unpack_exponent); | 1069 __ bind(&unpack_exponent); |
| 1070 __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear); | 1070 __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear); |
| 1071 __ SmiUntag(exponent); | 1071 __ SmiUntag(exponent); |
| 1072 __ jmp(&int_exponent); | 1072 __ jmp(&int_exponent); |
| 1073 | 1073 |
| 1074 __ bind(&exponent_not_smi); | 1074 __ bind(&exponent_not_smi); |
| 1075 __ cmp(FieldOperand(exponent, HeapObject::kMapOffset), | 1075 __ cmp(FieldOperand(exponent, HeapObject::kMapOffset), |
| 1076 factory->heap_number_map()); | 1076 factory->heap_number_map()); |
| 1077 __ j(not_equal, &call_runtime); | 1077 __ j(not_equal, &call_runtime); |
| 1078 __ movdbl(double_exponent, | 1078 __ movsd(double_exponent, |
| 1079 FieldOperand(exponent, HeapNumber::kValueOffset)); | 1079 FieldOperand(exponent, HeapNumber::kValueOffset)); |
| 1080 } else if (exponent_type_ == TAGGED) { | 1080 } else if (exponent_type_ == TAGGED) { |
| 1081 __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear); | 1081 __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear); |
| 1082 __ SmiUntag(exponent); | 1082 __ SmiUntag(exponent); |
| 1083 __ jmp(&int_exponent); | 1083 __ jmp(&int_exponent); |
| 1084 | 1084 |
| 1085 __ bind(&exponent_not_smi); | 1085 __ bind(&exponent_not_smi); |
| 1086 __ movdbl(double_exponent, | 1086 __ movsd(double_exponent, |
| 1087 FieldOperand(exponent, HeapNumber::kValueOffset)); | 1087 FieldOperand(exponent, HeapNumber::kValueOffset)); |
| 1088 } | 1088 } |
| 1089 | 1089 |
| 1090 if (exponent_type_ != INTEGER) { | 1090 if (exponent_type_ != INTEGER) { |
| 1091 Label fast_power, try_arithmetic_simplification; | 1091 Label fast_power, try_arithmetic_simplification; |
| 1092 __ DoubleToI(exponent, double_exponent, double_scratch, | 1092 __ DoubleToI(exponent, double_exponent, double_scratch, |
| 1093 TREAT_MINUS_ZERO_AS_ZERO, &try_arithmetic_simplification); | 1093 TREAT_MINUS_ZERO_AS_ZERO, &try_arithmetic_simplification); |
| 1094 __ jmp(&int_exponent); | 1094 __ jmp(&int_exponent); |
| 1095 | 1095 |
| 1096 __ bind(&try_arithmetic_simplification); | 1096 __ bind(&try_arithmetic_simplification); |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1171 __ divsd(double_result, double_exponent); | 1171 __ divsd(double_result, double_exponent); |
| 1172 __ jmp(&done); | 1172 __ jmp(&done); |
| 1173 } | 1173 } |
| 1174 | 1174 |
| 1175 // Using FPU instructions to calculate power. | 1175 // Using FPU instructions to calculate power. |
| 1176 Label fast_power_failed; | 1176 Label fast_power_failed; |
| 1177 __ bind(&fast_power); | 1177 __ bind(&fast_power); |
| 1178 __ fnclex(); // Clear flags to catch exceptions later. | 1178 __ fnclex(); // Clear flags to catch exceptions later. |
| 1179 // Transfer (B)ase and (E)xponent onto the FPU register stack. | 1179 // Transfer (B)ase and (E)xponent onto the FPU register stack. |
| 1180 __ sub(esp, Immediate(kDoubleSize)); | 1180 __ sub(esp, Immediate(kDoubleSize)); |
| 1181 __ movdbl(Operand(esp, 0), double_exponent); | 1181 __ movsd(Operand(esp, 0), double_exponent); |
| 1182 __ fld_d(Operand(esp, 0)); // E | 1182 __ fld_d(Operand(esp, 0)); // E |
| 1183 __ movdbl(Operand(esp, 0), double_base); | 1183 __ movsd(Operand(esp, 0), double_base); |
| 1184 __ fld_d(Operand(esp, 0)); // B, E | 1184 __ fld_d(Operand(esp, 0)); // B, E |
| 1185 | 1185 |
| 1186 // Exponent is in st(1) and base is in st(0) | 1186 // Exponent is in st(1) and base is in st(0) |
| 1187 // B ^ E = (2^(E * log2(B)) - 1) + 1 = (2^X - 1) + 1 for X = E * log2(B) | 1187 // B ^ E = (2^(E * log2(B)) - 1) + 1 = (2^X - 1) + 1 for X = E * log2(B) |
| 1188 // FYL2X calculates st(1) * log2(st(0)) | 1188 // FYL2X calculates st(1) * log2(st(0)) |
| 1189 __ fyl2x(); // X | 1189 __ fyl2x(); // X |
| 1190 __ fld(0); // X, X | 1190 __ fld(0); // X, X |
| 1191 __ frndint(); // rnd(X), X | 1191 __ frndint(); // rnd(X), X |
| 1192 __ fsub(1); // rnd(X), X-rnd(X) | 1192 __ fsub(1); // rnd(X), X-rnd(X) |
| 1193 __ fxch(1); // X - rnd(X), rnd(X) | 1193 __ fxch(1); // X - rnd(X), rnd(X) |
| 1194 // F2XM1 calculates 2^st(0) - 1 for -1 < st(0) < 1 | 1194 // F2XM1 calculates 2^st(0) - 1 for -1 < st(0) < 1 |
| 1195 __ f2xm1(); // 2^(X-rnd(X)) - 1, rnd(X) | 1195 __ f2xm1(); // 2^(X-rnd(X)) - 1, rnd(X) |
| 1196 __ fld1(); // 1, 2^(X-rnd(X)) - 1, rnd(X) | 1196 __ fld1(); // 1, 2^(X-rnd(X)) - 1, rnd(X) |
| 1197 __ faddp(1); // 2^(X-rnd(X)), rnd(X) | 1197 __ faddp(1); // 2^(X-rnd(X)), rnd(X) |
| 1198 // FSCALE calculates st(0) * 2^st(1) | 1198 // FSCALE calculates st(0) * 2^st(1) |
| 1199 __ fscale(); // 2^X, rnd(X) | 1199 __ fscale(); // 2^X, rnd(X) |
| 1200 __ fstp(1); // 2^X | 1200 __ fstp(1); // 2^X |
| 1201 // Bail out to runtime in case of exceptions in the status word. | 1201 // Bail out to runtime in case of exceptions in the status word. |
| 1202 __ fnstsw_ax(); | 1202 __ fnstsw_ax(); |
| 1203 __ test_b(eax, 0x5F); // We check for all but precision exception. | 1203 __ test_b(eax, 0x5F); // We check for all but precision exception. |
| 1204 __ j(not_zero, &fast_power_failed, Label::kNear); | 1204 __ j(not_zero, &fast_power_failed, Label::kNear); |
| 1205 __ fstp_d(Operand(esp, 0)); | 1205 __ fstp_d(Operand(esp, 0)); |
| 1206 __ movdbl(double_result, Operand(esp, 0)); | 1206 __ movsd(double_result, Operand(esp, 0)); |
| 1207 __ add(esp, Immediate(kDoubleSize)); | 1207 __ add(esp, Immediate(kDoubleSize)); |
| 1208 __ jmp(&done); | 1208 __ jmp(&done); |
| 1209 | 1209 |
| 1210 __ bind(&fast_power_failed); | 1210 __ bind(&fast_power_failed); |
| 1211 __ fninit(); | 1211 __ fninit(); |
| 1212 __ add(esp, Immediate(kDoubleSize)); | 1212 __ add(esp, Immediate(kDoubleSize)); |
| 1213 __ jmp(&call_runtime); | 1213 __ jmp(&call_runtime); |
| 1214 } | 1214 } |
| 1215 | 1215 |
| 1216 // Calculate power with integer exponent. | 1216 // Calculate power with integer exponent. |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1263 Counters* counters = masm->isolate()->counters(); | 1263 Counters* counters = masm->isolate()->counters(); |
| 1264 if (exponent_type_ == ON_STACK) { | 1264 if (exponent_type_ == ON_STACK) { |
| 1265 // The arguments are still on the stack. | 1265 // The arguments are still on the stack. |
| 1266 __ bind(&call_runtime); | 1266 __ bind(&call_runtime); |
| 1267 __ TailCallRuntime(Runtime::kMath_pow_cfunction, 2, 1); | 1267 __ TailCallRuntime(Runtime::kMath_pow_cfunction, 2, 1); |
| 1268 | 1268 |
| 1269 // The stub is called from non-optimized code, which expects the result | 1269 // The stub is called from non-optimized code, which expects the result |
| 1270 // as heap number in exponent. | 1270 // as heap number in exponent. |
| 1271 __ bind(&done); | 1271 __ bind(&done); |
| 1272 __ AllocateHeapNumber(eax, scratch, base, &call_runtime); | 1272 __ AllocateHeapNumber(eax, scratch, base, &call_runtime); |
| 1273 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), double_result); | 1273 __ movsd(FieldOperand(eax, HeapNumber::kValueOffset), double_result); |
| 1274 __ IncrementCounter(counters->math_pow(), 1); | 1274 __ IncrementCounter(counters->math_pow(), 1); |
| 1275 __ ret(2 * kPointerSize); | 1275 __ ret(2 * kPointerSize); |
| 1276 } else { | 1276 } else { |
| 1277 __ bind(&call_runtime); | 1277 __ bind(&call_runtime); |
| 1278 { | 1278 { |
| 1279 AllowExternalCallThatCantCauseGC scope(masm); | 1279 AllowExternalCallThatCantCauseGC scope(masm); |
| 1280 __ PrepareCallCFunction(4, scratch); | 1280 __ PrepareCallCFunction(4, scratch); |
| 1281 __ movdbl(Operand(esp, 0 * kDoubleSize), double_base); | 1281 __ movsd(Operand(esp, 0 * kDoubleSize), double_base); |
| 1282 __ movdbl(Operand(esp, 1 * kDoubleSize), double_exponent); | 1282 __ movsd(Operand(esp, 1 * kDoubleSize), double_exponent); |
| 1283 __ CallCFunction( | 1283 __ CallCFunction( |
| 1284 ExternalReference::power_double_double_function(masm->isolate()), 4); | 1284 ExternalReference::power_double_double_function(masm->isolate()), 4); |
| 1285 } | 1285 } |
| 1286 // Return value is in st(0) on ia32. | 1286 // Return value is in st(0) on ia32. |
| 1287 // Store it into the (fixed) result register. | 1287 // Store it into the (fixed) result register. |
| 1288 __ sub(esp, Immediate(kDoubleSize)); | 1288 __ sub(esp, Immediate(kDoubleSize)); |
| 1289 __ fstp_d(Operand(esp, 0)); | 1289 __ fstp_d(Operand(esp, 0)); |
| 1290 __ movdbl(double_result, Operand(esp, 0)); | 1290 __ movsd(double_result, Operand(esp, 0)); |
| 1291 __ add(esp, Immediate(kDoubleSize)); | 1291 __ add(esp, Immediate(kDoubleSize)); |
| 1292 | 1292 |
| 1293 __ bind(&done); | 1293 __ bind(&done); |
| 1294 __ IncrementCounter(counters->math_pow(), 1); | 1294 __ IncrementCounter(counters->math_pow(), 1); |
| 1295 __ ret(0); | 1295 __ ret(0); |
| 1296 } | 1296 } |
| 1297 } | 1297 } |
| 1298 | 1298 |
| 1299 | 1299 |
| 1300 void FunctionPrototypeStub::Generate(MacroAssembler* masm) { | 1300 void FunctionPrototypeStub::Generate(MacroAssembler* masm) { |
| (...skipping 3422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4723 if (CpuFeatures::IsSupported(SSE2) && CpuFeatures::IsSupported(CMOV)) { | 4723 if (CpuFeatures::IsSupported(SSE2) && CpuFeatures::IsSupported(CMOV)) { |
| 4724 CpuFeatureScope scope1(masm, SSE2); | 4724 CpuFeatureScope scope1(masm, SSE2); |
| 4725 CpuFeatureScope scope2(masm, CMOV); | 4725 CpuFeatureScope scope2(masm, CMOV); |
| 4726 | 4726 |
| 4727 // Load left and right operand. | 4727 // Load left and right operand. |
| 4728 Label done, left, left_smi, right_smi; | 4728 Label done, left, left_smi, right_smi; |
| 4729 __ JumpIfSmi(eax, &right_smi, Label::kNear); | 4729 __ JumpIfSmi(eax, &right_smi, Label::kNear); |
| 4730 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), | 4730 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), |
| 4731 masm->isolate()->factory()->heap_number_map()); | 4731 masm->isolate()->factory()->heap_number_map()); |
| 4732 __ j(not_equal, &maybe_undefined1, Label::kNear); | 4732 __ j(not_equal, &maybe_undefined1, Label::kNear); |
| 4733 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); | 4733 __ movsd(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); |
| 4734 __ jmp(&left, Label::kNear); | 4734 __ jmp(&left, Label::kNear); |
| 4735 __ bind(&right_smi); | 4735 __ bind(&right_smi); |
| 4736 __ mov(ecx, eax); // Can't clobber eax because we can still jump away. | 4736 __ mov(ecx, eax); // Can't clobber eax because we can still jump away. |
| 4737 __ SmiUntag(ecx); | 4737 __ SmiUntag(ecx); |
| 4738 __ Cvtsi2sd(xmm1, ecx); | 4738 __ Cvtsi2sd(xmm1, ecx); |
| 4739 | 4739 |
| 4740 __ bind(&left); | 4740 __ bind(&left); |
| 4741 __ JumpIfSmi(edx, &left_smi, Label::kNear); | 4741 __ JumpIfSmi(edx, &left_smi, Label::kNear); |
| 4742 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 4742 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
| 4743 masm->isolate()->factory()->heap_number_map()); | 4743 masm->isolate()->factory()->heap_number_map()); |
| 4744 __ j(not_equal, &maybe_undefined2, Label::kNear); | 4744 __ j(not_equal, &maybe_undefined2, Label::kNear); |
| 4745 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); | 4745 __ movsd(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); |
| 4746 __ jmp(&done); | 4746 __ jmp(&done); |
| 4747 __ bind(&left_smi); | 4747 __ bind(&left_smi); |
| 4748 __ mov(ecx, edx); // Can't clobber edx because we can still jump away. | 4748 __ mov(ecx, edx); // Can't clobber edx because we can still jump away. |
| 4749 __ SmiUntag(ecx); | 4749 __ SmiUntag(ecx); |
| 4750 __ Cvtsi2sd(xmm0, ecx); | 4750 __ Cvtsi2sd(xmm0, ecx); |
| 4751 | 4751 |
| 4752 __ bind(&done); | 4752 __ bind(&done); |
| 4753 // Compare operands. | 4753 // Compare operands. |
| 4754 __ ucomisd(xmm0, xmm1); | 4754 __ ucomisd(xmm0, xmm1); |
| 4755 | 4755 |
| (...skipping 1266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6022 __ bind(&fast_elements_case); | 6022 __ bind(&fast_elements_case); |
| 6023 GenerateCase(masm, FAST_ELEMENTS); | 6023 GenerateCase(masm, FAST_ELEMENTS); |
| 6024 } | 6024 } |
| 6025 | 6025 |
| 6026 | 6026 |
| 6027 #undef __ | 6027 #undef __ |
| 6028 | 6028 |
| 6029 } } // namespace v8::internal | 6029 } } // namespace v8::internal |
| 6030 | 6030 |
| 6031 #endif // V8_TARGET_ARCH_IA32 | 6031 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |