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 4826 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4837 | 4837 |
4838 __ CallRuntime(TargetFunction(), InputCount()); | 4838 __ CallRuntime(TargetFunction(), InputCount()); |
4839 __ fstpl(Address(ESP, 0)); | 4839 __ fstpl(Address(ESP, 0)); |
4840 __ movsd(locs()->out(0).fpu_reg(), Address(ESP, 0)); | 4840 __ movsd(locs()->out(0).fpu_reg(), Address(ESP, 0)); |
4841 __ Bind(&skip_call); | 4841 __ Bind(&skip_call); |
4842 // Restore ESP. | 4842 // Restore ESP. |
4843 __ movl(ESP, locs()->temp(kSavedSpTempIndex).reg()); | 4843 __ movl(ESP, locs()->temp(kSavedSpTempIndex).reg()); |
4844 } | 4844 } |
4845 | 4845 |
4846 | 4846 |
4847 LocationSummary* MergedMathInstr::MakeLocationSummary(bool opt) const { | 4847 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(bool opt) const { |
4848 if (kind() == MergedMathInstr::kTruncDivMod) { | 4848 // Only use this instruction in optimized code. |
4849 ASSERT(opt); | |
4850 const intptr_t kNumInputs = 1; | |
4851 LocationSummary* summary = | |
4852 new LocationSummary(kNumInputs, 0, LocationSummary::kNoCall); | |
4853 if (representation() == kUnboxedDouble) { | |
4854 if (index() == 0) { | |
4855 summary->set_in(0, Location::Pair(Location::RequiresFpuRegister(), | |
4856 Location::Any())); | |
4857 } else { | |
4858 ASSERT(index() == 1); | |
4859 summary->set_in(0, Location::Pair(Location::Any(), | |
4860 Location::RequiresFpuRegister())); | |
4861 } | |
4862 summary->set_out(0, Location::RequiresFpuRegister()); | |
4863 } else { | |
4864 ASSERT(representation() == kTagged); | |
4865 if (index() == 0) { | |
4866 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | |
4867 Location::Any())); | |
4868 } else { | |
4869 ASSERT(index() == 1); | |
4870 summary->set_in(0, Location::Pair(Location::Any(), | |
4871 Location::RequiresRegister())); | |
4872 } | |
4873 summary->set_out(0, Location::RequiresRegister()); | |
4874 } | |
4875 return summary; | |
4876 } | |
4877 | |
4878 | |
4879 void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
4880 ASSERT(locs()->in(0).IsPairLocation()); | |
4881 PairLocation* pair = locs()->in(0).AsPairLocation(); | |
4882 Location in_loc = pair->At(index()); | |
4883 if (representation() == kUnboxedDouble) { | |
4884 XmmRegister out = locs()->out(0).fpu_reg(); | |
4885 XmmRegister in = in_loc.fpu_reg(); | |
4886 __ movaps(out, in); | |
4887 } else { | |
4888 ASSERT(representation() == kTagged); | |
4889 Register out = locs()->out(0).reg(); | |
4890 Register in = in_loc.reg(); | |
4891 __ movl(out, in); | |
4892 } | |
4893 } | |
4894 | |
4895 | |
4896 LocationSummary* MergedMath2Instr::MakeLocationSummary(bool opt) const { | |
4897 if (kind() == MergedMath2Instr::kTruncDivMod) { | |
4849 const intptr_t kNumInputs = 2; | 4898 const intptr_t kNumInputs = 2; |
4850 const intptr_t kNumTemps = 1; | 4899 const intptr_t kNumTemps = 1; |
4851 LocationSummary* summary = | 4900 LocationSummary* summary = |
4852 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4901 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4853 // Both inputs must be writable because they will be untagged. | 4902 // Both inputs must be writable because they will be untagged. |
4854 summary->set_in(0, Location::RegisterLocation(EAX)); | 4903 summary->set_in(0, Location::RegisterLocation(EAX)); |
4855 summary->set_in(1, Location::WritableRegister()); | 4904 summary->set_in(1, Location::WritableRegister()); |
4856 summary->set_out(0, Location::RequiresRegister()); | 4905 // Output is a pair of registers. |
4906 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | |
4907 Location::RequiresRegister())); | |
4857 // Will be used for sign extension and division. | 4908 // Will be used for sign extension and division. |
4858 summary->set_temp(0, Location::RegisterLocation(EDX)); | 4909 summary->set_temp(0, Location::RegisterLocation(EDX)); |
4859 return summary; | 4910 return summary; |
4860 } | 4911 } |
4861 if (kind() == MergedMathInstr::kSinCos) { | 4912 if (kind() == MergedMath2Instr::kSinCos) { |
4862 const intptr_t kNumInputs = 1; | 4913 const intptr_t kNumInputs = 1; |
4863 const intptr_t kNumTemps = 0; | 4914 const intptr_t kNumTemps = 0; |
4864 LocationSummary* summary = | 4915 LocationSummary* summary = |
4865 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 4916 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4866 summary->set_in(0, Location::FpuRegisterLocation(XMM1)); | 4917 summary->set_in(0, Location::RequiresFpuRegister()); |
4867 summary->set_out(0, Location::RegisterLocation(EAX)); | 4918 summary->set_out(0, Location::Pair(Location::RequiresFpuRegister(), |
4919 Location::RequiresFpuRegister())); | |
4868 return summary; | 4920 return summary; |
4869 } | 4921 } |
4870 UNIMPLEMENTED(); | 4922 UNIMPLEMENTED(); |
4871 return NULL; | 4923 return NULL; |
4872 } | 4924 } |
4873 | 4925 |
4874 | 4926 |
4875 typedef void (*SinCosCFunction) (double x, double* res_sin, double* res_cos); | 4927 typedef void (*SinCosCFunction) (double x, double* res_sin, double* res_cos); |
4876 | 4928 |
4877 extern const RuntimeEntry kSinCosRuntimeEntry( | 4929 extern const RuntimeEntry kSinCosRuntimeEntry( |
4878 "libc_sincos", reinterpret_cast<RuntimeFunction>( | 4930 "libc_sincos", reinterpret_cast<RuntimeFunction>( |
4879 static_cast<SinCosCFunction>(&SinCos)), 1, true, true); | 4931 static_cast<SinCosCFunction>(&SinCos)), 1, true, true); |
4880 | 4932 |
4881 | 4933 |
4934 void MergedMath2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
4935 Label* deopt = NULL; | |
4936 if (CanDeoptimize()) { | |
4937 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp); | |
4938 } | |
4939 | |
4940 if (kind() == MergedMath2Instr::kTruncDivMod) { | |
4941 Register left = locs()->in(0).reg(); | |
4942 Register right = locs()->in(1).reg(); | |
4943 ASSERT(locs()->out(0).IsPairLocation()); | |
4944 PairLocation* pair = locs()->out(0).AsPairLocation(); | |
4945 Register result1 = pair->At(0).reg(); | |
4946 Register result2 = pair->At(1).reg(); | |
4947 Range* right_range = InputAt(1)->definition()->range(); | |
4948 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { | |
4949 // Handle divide by zero in runtime. | |
4950 __ testl(right, right); | |
4951 __ j(ZERO, deopt); | |
4952 } | |
4953 ASSERT(left == EAX); | |
4954 ASSERT((right != EDX) && (right != EAX)); | |
4955 ASSERT(locs()->temp(0).reg() == EDX); | |
4956 ASSERT((result1 != EDX) && (result1 != EAX)); | |
4957 ASSERT((result2 != EDX) && (result2 != EAX)); | |
4958 __ SmiUntag(left); | |
4959 __ SmiUntag(right); | |
4960 __ cdq(); // Sign extend EAX -> EDX:EAX. | |
4961 __ idivl(right); // EAX: quotient, EDX: remainder. | |
4962 // Check the corner case of dividing the 'MIN_SMI' with -1, in which | |
4963 // case we cannot tag the result. | |
4964 // TODO(srdjan): We could store instead untagged intermediate results in a | |
4965 // typed array, but then the load indexed instructions would need to be | |
4966 // able to deoptimize. | |
4967 __ cmpl(EAX, Immediate(0x40000000)); | |
4968 __ j(EQUAL, deopt); | |
4969 // Modulo result (EDX) correction: | |
4970 // res = left % right; | |
4971 // if (res < 0) { | |
4972 // if (right < 0) { | |
4973 // res = res - right; | |
4974 // } else { | |
4975 // res = res + right; | |
4976 // } | |
4977 // } | |
4978 Label done; | |
4979 __ cmpl(EDX, Immediate(0)); | |
4980 __ j(GREATER_EQUAL, &done, Assembler::kNearJump); | |
4981 // Result is negative, adjust it. | |
4982 if ((right_range == NULL) || right_range->Overlaps(-1, 1)) { | |
4983 Label subtract; | |
4984 __ cmpl(right, Immediate(0)); | |
4985 __ j(LESS, &subtract, Assembler::kNearJump); | |
4986 __ addl(EDX, right); | |
4987 __ jmp(&done, Assembler::kNearJump); | |
4988 __ Bind(&subtract); | |
4989 __ subl(EDX, right); | |
4990 } else if (right_range->IsWithin(0, RangeBoundary::kPlusInfinity)) { | |
4991 // Right is positive. | |
4992 __ addl(EDX, right); | |
4993 } else { | |
4994 // Right is negative. | |
4995 __ subl(EDX, right); | |
4996 } | |
4997 __ Bind(&done); | |
4998 | |
4999 __ SmiTag(EAX); | |
5000 __ SmiTag(EDX); | |
5001 __ movl(result1, EAX); | |
5002 __ movl(result2, EDX); | |
5003 return; | |
5004 } | |
5005 | |
5006 if (kind() == MergedMath2Instr::kSinCos) { | |
5007 XmmRegister in = locs()->in(0).fpu_reg(); | |
5008 ASSERT(locs()->out(0).IsPairLocation()); | |
5009 PairLocation* pair = locs()->out(0).AsPairLocation(); | |
5010 XmmRegister out1 = pair->At(0).fpu_reg(); | |
5011 XmmRegister out2 = pair->At(1).fpu_reg(); | |
5012 | |
5013 // Do x87 sincos, since the ia32 compilers may not fuse sin/cos into | |
5014 // sincos. | |
5015 __ pushl(EAX); | |
5016 __ pushl(EAX); | |
5017 __ movsd(Address(ESP, 0), in); | |
5018 __ fldl(Address(ESP, 0)); | |
5019 __ fsincos(); | |
5020 __ fstpl(Address(ESP, 0)); | |
5021 __ movsd(out1, Address(ESP, 0)); | |
5022 __ fstpl(Address(ESP, 0)); | |
5023 __ movsd(out2, Address(ESP, 0)); | |
5024 __ addl(ESP, Immediate(2 * kWordSize)); | |
5025 return; | |
5026 } | |
5027 | |
5028 UNIMPLEMENTED(); | |
5029 } | |
5030 | |
5031 | |
5032 LocationSummary* MergedMathInstr::MakeLocationSummary(bool opt) const { | |
5033 if (kind() == MergedMathInstr::kTruncDivMod) { | |
5034 const intptr_t kNumInputs = 2; | |
5035 const intptr_t kNumTemps = 1; | |
5036 LocationSummary* summary = | |
5037 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
5038 // Both inputs must be writable because they will be untagged. | |
5039 summary->set_in(0, Location::RegisterLocation(EAX)); | |
5040 summary->set_in(1, Location::WritableRegister()); | |
5041 summary->set_out(0, Location::RequiresRegister()); | |
5042 // Will be used for sign extension and division. | |
5043 summary->set_temp(0, Location::RegisterLocation(EDX)); | |
5044 return summary; | |
5045 } | |
5046 if (kind() == MergedMathInstr::kSinCos) { | |
Florian Schneider
2014/04/04 11:52:46
I wonder how much code is actually shared between
Cutch
2014/04/04 16:34:46
Note that this is a clone of MergedMathInstr that
| |
5047 const intptr_t kNumInputs = 1; | |
5048 const intptr_t kNumTemps = 0; | |
5049 LocationSummary* summary = | |
5050 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | |
5051 summary->set_in(0, Location::FpuRegisterLocation(XMM1)); | |
5052 summary->set_out(0, Location::RegisterLocation(EAX)); | |
5053 return summary; | |
5054 } | |
5055 UNIMPLEMENTED(); | |
5056 return NULL; | |
5057 } | |
5058 | |
5059 | |
4882 void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5060 void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4883 Label* deopt = NULL; | 5061 Label* deopt = NULL; |
4884 if (CanDeoptimize()) { | 5062 if (CanDeoptimize()) { |
4885 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp); | 5063 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp); |
4886 } | 5064 } |
4887 | 5065 |
4888 if (kind() == MergedMathInstr::kTruncDivMod) { | 5066 if (kind() == MergedMathInstr::kTruncDivMod) { |
4889 Register left = locs()->in(0).reg(); | 5067 Register left = locs()->in(0).reg(); |
4890 Register right = locs()->in(1).reg(); | 5068 Register right = locs()->in(1).reg(); |
4891 Register result = locs()->out(0).reg(); | 5069 Register result = locs()->out(0).reg(); |
(...skipping 947 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5839 PcDescriptors::kOther, | 6017 PcDescriptors::kOther, |
5840 locs()); | 6018 locs()); |
5841 __ Drop(ArgumentCount()); // Discard arguments. | 6019 __ Drop(ArgumentCount()); // Discard arguments. |
5842 } | 6020 } |
5843 | 6021 |
5844 } // namespace dart | 6022 } // namespace dart |
5845 | 6023 |
5846 #undef __ | 6024 #undef __ |
5847 | 6025 |
5848 #endif // defined TARGET_ARCH_IA32 | 6026 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |