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 |