Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/ia32/code-stubs-ia32.cc

Issue 27197013: Tweak Math.log on ia32/x64 (Closed) Base URL: git://github.com/v8/v8.git@master
Patch Set: addressed comments Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/ia32/code-stubs-ia32.h ('k') | src/ia32/codegen-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/ia32/code-stubs-ia32.h ('k') | src/ia32/codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698