OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
7 | 7 |
8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
9 | 9 |
10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
(...skipping 4829 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4840 | 4840 |
4841 __ CallRuntime(TargetFunction(), InputCount()); | 4841 __ CallRuntime(TargetFunction(), InputCount()); |
4842 __ fstpl(Address(ESP, 0)); | 4842 __ fstpl(Address(ESP, 0)); |
4843 __ movsd(locs()->out(0).fpu_reg(), Address(ESP, 0)); | 4843 __ movsd(locs()->out(0).fpu_reg(), Address(ESP, 0)); |
4844 __ Bind(&skip_call); | 4844 __ Bind(&skip_call); |
4845 // Restore ESP. | 4845 // Restore ESP. |
4846 __ movl(ESP, locs()->temp(kSavedSpTempIndex).reg()); | 4846 __ movl(ESP, locs()->temp(kSavedSpTempIndex).reg()); |
4847 } | 4847 } |
4848 | 4848 |
4849 | 4849 |
| 4850 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(bool opt) const { |
| 4851 // Only use this instruction in optimized code. |
| 4852 ASSERT(opt); |
| 4853 const intptr_t kNumInputs = 1; |
| 4854 LocationSummary* summary = |
| 4855 new LocationSummary(kNumInputs, 0, LocationSummary::kNoCall); |
| 4856 if (representation() == kUnboxedDouble) { |
| 4857 if (index() == 0) { |
| 4858 summary->set_in(0, Location::Pair(Location::RequiresFpuRegister(), |
| 4859 Location::Any())); |
| 4860 } else { |
| 4861 ASSERT(index() == 1); |
| 4862 summary->set_in(0, Location::Pair(Location::Any(), |
| 4863 Location::RequiresFpuRegister())); |
| 4864 } |
| 4865 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4866 } else { |
| 4867 ASSERT(representation() == kTagged); |
| 4868 if (index() == 0) { |
| 4869 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 4870 Location::Any())); |
| 4871 } else { |
| 4872 ASSERT(index() == 1); |
| 4873 summary->set_in(0, Location::Pair(Location::Any(), |
| 4874 Location::RequiresRegister())); |
| 4875 } |
| 4876 summary->set_out(0, Location::RequiresRegister()); |
| 4877 } |
| 4878 return summary; |
| 4879 } |
| 4880 |
| 4881 |
| 4882 void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4883 ASSERT(locs()->in(0).IsPairLocation()); |
| 4884 PairLocation* pair = locs()->in(0).AsPairLocation(); |
| 4885 Location in_loc = pair->At(index()); |
| 4886 if (representation() == kUnboxedDouble) { |
| 4887 XmmRegister out = locs()->out(0).fpu_reg(); |
| 4888 XmmRegister in = in_loc.fpu_reg(); |
| 4889 __ movaps(out, in); |
| 4890 } else { |
| 4891 ASSERT(representation() == kTagged); |
| 4892 Register out = locs()->out(0).reg(); |
| 4893 Register in = in_loc.reg(); |
| 4894 __ movl(out, in); |
| 4895 } |
| 4896 } |
| 4897 |
| 4898 |
4850 LocationSummary* MergedMathInstr::MakeLocationSummary(bool opt) const { | 4899 LocationSummary* MergedMathInstr::MakeLocationSummary(bool opt) const { |
4851 if (kind() == MergedMathInstr::kTruncDivMod) { | 4900 if (kind() == MergedMathInstr::kTruncDivMod) { |
4852 const intptr_t kNumInputs = 2; | 4901 const intptr_t kNumInputs = 2; |
4853 const intptr_t kNumTemps = 1; | 4902 const intptr_t kNumTemps = 0; |
4854 LocationSummary* summary = | 4903 LocationSummary* summary = |
4855 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4904 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4856 // Both inputs must be writable because they will be untagged. | 4905 // Both inputs must be writable because they will be untagged. |
4857 summary->set_in(0, Location::RegisterLocation(EAX)); | 4906 summary->set_in(0, Location::RegisterLocation(EAX)); |
4858 summary->set_in(1, Location::WritableRegister()); | 4907 summary->set_in(1, Location::WritableRegister()); |
4859 summary->set_out(0, Location::RequiresRegister()); | 4908 // Output is a pair of registers. |
4860 // Will be used for sign extension and division. | 4909 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX), |
4861 summary->set_temp(0, Location::RegisterLocation(EDX)); | 4910 Location::RegisterLocation(EDX))); |
4862 return summary; | 4911 return summary; |
4863 } | 4912 } |
4864 if (kind() == MergedMathInstr::kSinCos) { | 4913 if (kind() == MergedMathInstr::kSinCos) { |
4865 const intptr_t kNumInputs = 1; | 4914 const intptr_t kNumInputs = 1; |
4866 const intptr_t kNumTemps = 0; | 4915 const intptr_t kNumTemps = 0; |
4867 LocationSummary* summary = | 4916 LocationSummary* summary = |
4868 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 4917 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4869 summary->set_in(0, Location::FpuRegisterLocation(XMM1)); | 4918 summary->set_in(0, Location::RequiresFpuRegister()); |
4870 summary->set_out(0, Location::RegisterLocation(EAX)); | 4919 summary->set_out(0, Location::Pair(Location::RequiresFpuRegister(), |
| 4920 Location::RequiresFpuRegister())); |
4871 return summary; | 4921 return summary; |
4872 } | 4922 } |
4873 UNIMPLEMENTED(); | 4923 UNIMPLEMENTED(); |
4874 return NULL; | 4924 return NULL; |
4875 } | 4925 } |
4876 | 4926 |
4877 | 4927 |
4878 typedef void (*SinCosCFunction) (double x, double* res_sin, double* res_cos); | 4928 typedef void (*SinCosCFunction) (double x, double* res_sin, double* res_cos); |
4879 | 4929 |
4880 extern const RuntimeEntry kSinCosRuntimeEntry( | 4930 extern const RuntimeEntry kSinCosRuntimeEntry( |
4881 "libc_sincos", reinterpret_cast<RuntimeFunction>( | 4931 "libc_sincos", reinterpret_cast<RuntimeFunction>( |
4882 static_cast<SinCosCFunction>(&SinCos)), 1, true, true); | 4932 static_cast<SinCosCFunction>(&SinCos)), 1, true, true); |
4883 | 4933 |
4884 | 4934 |
4885 void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4935 void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4886 Label* deopt = NULL; | 4936 Label* deopt = NULL; |
4887 if (CanDeoptimize()) { | 4937 if (CanDeoptimize()) { |
4888 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp); | 4938 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp); |
4889 } | 4939 } |
4890 | 4940 |
4891 if (kind() == MergedMathInstr::kTruncDivMod) { | 4941 if (kind() == MergedMathInstr::kTruncDivMod) { |
4892 Register left = locs()->in(0).reg(); | 4942 Register left = locs()->in(0).reg(); |
4893 Register right = locs()->in(1).reg(); | 4943 Register right = locs()->in(1).reg(); |
4894 Register result = locs()->out(0).reg(); | 4944 ASSERT(locs()->out(0).IsPairLocation()); |
| 4945 PairLocation* pair = locs()->out(0).AsPairLocation(); |
| 4946 Register result1 = pair->At(0).reg(); |
| 4947 Register result2 = pair->At(1).reg(); |
4895 Range* right_range = InputAt(1)->definition()->range(); | 4948 Range* right_range = InputAt(1)->definition()->range(); |
4896 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { | 4949 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { |
4897 // Handle divide by zero in runtime. | 4950 // Handle divide by zero in runtime. |
4898 __ testl(right, right); | 4951 __ testl(right, right); |
4899 __ j(ZERO, deopt); | 4952 __ j(ZERO, deopt); |
4900 } | 4953 } |
4901 ASSERT(left == EAX); | 4954 ASSERT(left == EAX); |
4902 ASSERT((right != EDX) && (right != EAX)); | 4955 ASSERT((right != EDX) && (right != EAX)); |
4903 ASSERT(locs()->temp(0).reg() == EDX); | 4956 ASSERT(result1 == EAX); |
4904 ASSERT((result != EDX) && (result != EAX)); | 4957 ASSERT(result2 == EDX); |
4905 __ SmiUntag(left); | 4958 __ SmiUntag(left); |
4906 __ SmiUntag(right); | 4959 __ SmiUntag(right); |
4907 __ cdq(); // Sign extend EAX -> EDX:EAX. | 4960 __ cdq(); // Sign extend EAX -> EDX:EAX. |
4908 __ idivl(right); // EAX: quotient, EDX: remainder. | 4961 __ idivl(right); // EAX: quotient, EDX: remainder. |
4909 // Check the corner case of dividing the 'MIN_SMI' with -1, in which | 4962 // Check the corner case of dividing the 'MIN_SMI' with -1, in which |
4910 // case we cannot tag the result. | 4963 // case we cannot tag the result. |
4911 // TODO(srdjan): We could store instead untagged intermediate results in a | 4964 // TODO(srdjan): We could store instead untagged intermediate results in a |
4912 // typed array, but then the load indexed instructions would need to be | 4965 // typed array, but then the load indexed instructions would need to be |
4913 // able to deoptimize. | 4966 // able to deoptimize. |
4914 __ cmpl(EAX, Immediate(0x40000000)); | 4967 __ cmpl(EAX, Immediate(0x40000000)); |
(...skipping 21 matching lines...) Expand all Loading... |
4936 __ subl(EDX, right); | 4989 __ subl(EDX, right); |
4937 } else if (right_range->IsWithin(0, RangeBoundary::kPlusInfinity)) { | 4990 } else if (right_range->IsWithin(0, RangeBoundary::kPlusInfinity)) { |
4938 // Right is positive. | 4991 // Right is positive. |
4939 __ addl(EDX, right); | 4992 __ addl(EDX, right); |
4940 } else { | 4993 } else { |
4941 // Right is negative. | 4994 // Right is negative. |
4942 __ subl(EDX, right); | 4995 __ subl(EDX, right); |
4943 } | 4996 } |
4944 __ Bind(&done); | 4997 __ Bind(&done); |
4945 | 4998 |
4946 __ LoadObject(result, Array::ZoneHandle(Array::New(2, Heap::kOld))); | |
4947 const intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(kArrayCid); | |
4948 Address trunc_div_address( | |
4949 FlowGraphCompiler::ElementAddressForIntIndex( | |
4950 kArrayCid, index_scale, result, | |
4951 MergedMathInstr::ResultIndexOf(Token::kTRUNCDIV))); | |
4952 Address mod_address( | |
4953 FlowGraphCompiler::ElementAddressForIntIndex( | |
4954 kArrayCid, index_scale, result, | |
4955 MergedMathInstr::ResultIndexOf(Token::kMOD))); | |
4956 __ SmiTag(EAX); | 4999 __ SmiTag(EAX); |
4957 __ SmiTag(EDX); | 5000 __ SmiTag(EDX); |
4958 __ StoreIntoObjectNoBarrier(result, trunc_div_address, EAX); | |
4959 __ StoreIntoObjectNoBarrier(result, mod_address, EDX); | |
4960 return; | 5001 return; |
4961 } | 5002 } |
4962 | 5003 |
4963 if (kind() == MergedMathInstr::kSinCos) { | 5004 if (kind() == MergedMathInstr::kSinCos) { |
| 5005 XmmRegister in = locs()->in(0).fpu_reg(); |
| 5006 ASSERT(locs()->out(0).IsPairLocation()); |
| 5007 PairLocation* pair = locs()->out(0).AsPairLocation(); |
| 5008 XmmRegister out1 = pair->At(0).fpu_reg(); |
| 5009 XmmRegister out2 = pair->At(1).fpu_reg(); |
| 5010 |
4964 // Do x87 sincos, since the ia32 compilers may not fuse sin/cos into | 5011 // Do x87 sincos, since the ia32 compilers may not fuse sin/cos into |
4965 // sincos. | 5012 // sincos. |
4966 __ pushl(EAX); | 5013 __ pushl(EAX); |
4967 __ pushl(EAX); | 5014 __ pushl(EAX); |
4968 __ movsd(Address(ESP, 0), locs()->in(0).fpu_reg()); | 5015 __ movsd(Address(ESP, 0), in); |
4969 __ fldl(Address(ESP, 0)); | 5016 __ fldl(Address(ESP, 0)); |
4970 __ fsincos(); | 5017 __ fsincos(); |
4971 __ fstpl(Address(ESP, 0)); | 5018 __ fstpl(Address(ESP, 0)); |
4972 __ movsd(XMM1, Address(ESP, 0)); | 5019 __ movsd(out1, Address(ESP, 0)); |
4973 __ fstpl(Address(ESP, 0)); | 5020 __ fstpl(Address(ESP, 0)); |
4974 __ movsd(XMM0, Address(ESP, 0)); | 5021 __ movsd(out2, Address(ESP, 0)); |
4975 __ addl(ESP, Immediate(2 * kWordSize)); | 5022 __ addl(ESP, Immediate(2 * kWordSize)); |
4976 | |
4977 Register result = locs()->out(0).reg(); | |
4978 const TypedData& res_array = TypedData::ZoneHandle( | |
4979 TypedData::New(kTypedDataFloat64ArrayCid, 2, Heap::kOld)); | |
4980 __ LoadObject(result, res_array); | |
4981 const intptr_t index_scale = | |
4982 FlowGraphCompiler::ElementSizeFor(kTypedDataFloat64ArrayCid); | |
4983 Address sin_address( | |
4984 FlowGraphCompiler::ElementAddressForIntIndex( | |
4985 kTypedDataFloat64ArrayCid, index_scale, result, | |
4986 MergedMathInstr::ResultIndexOf(MethodRecognizer::kMathSin))); | |
4987 Address cos_address( | |
4988 FlowGraphCompiler::ElementAddressForIntIndex( | |
4989 kTypedDataFloat64ArrayCid, index_scale, result, | |
4990 MergedMathInstr::ResultIndexOf(MethodRecognizer::kMathCos))); | |
4991 __ movsd(sin_address, XMM0); | |
4992 __ movsd(cos_address, XMM1); | |
4993 return; | 5023 return; |
4994 } | 5024 } |
4995 | 5025 |
4996 UNIMPLEMENTED(); | 5026 UNIMPLEMENTED(); |
4997 } | 5027 } |
4998 | 5028 |
4999 | 5029 |
5000 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( | 5030 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( |
5001 bool opt) const { | 5031 bool opt) const { |
5002 return MakeCallSummary(); | 5032 return MakeCallSummary(); |
(...skipping 839 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5842 PcDescriptors::kOther, | 5872 PcDescriptors::kOther, |
5843 locs()); | 5873 locs()); |
5844 __ Drop(ArgumentCount()); // Discard arguments. | 5874 __ Drop(ArgumentCount()); // Discard arguments. |
5845 } | 5875 } |
5846 | 5876 |
5847 } // namespace dart | 5877 } // namespace dart |
5848 | 5878 |
5849 #undef __ | 5879 #undef __ |
5850 | 5880 |
5851 #endif // defined TARGET_ARCH_IA32 | 5881 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |