OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
7 | 7 |
8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
9 | 9 |
10 #include "lib/error.h" | 10 #include "lib/error.h" |
(...skipping 918 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
929 return Utils::IsInt(32, disp); | 929 return Utils::IsInt(32, disp); |
930 } | 930 } |
931 | 931 |
932 | 932 |
933 LocationSummary* StringCharCodeAtInstr::MakeLocationSummary() const { | 933 LocationSummary* StringCharCodeAtInstr::MakeLocationSummary() const { |
934 const intptr_t kNumInputs = 2; | 934 const intptr_t kNumInputs = 2; |
935 const intptr_t kNumTemps = 0; | 935 const intptr_t kNumTemps = 0; |
936 LocationSummary* locs = | 936 LocationSummary* locs = |
937 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 937 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
938 locs->set_in(0, Location::RequiresRegister()); | 938 locs->set_in(0, Location::RequiresRegister()); |
| 939 // The smi index is either untagged and tagged again at the end of the |
| 940 // operation (element size == 1), or it is left smi tagged (for all element |
| 941 // sizes > 1). |
939 locs->set_in(1, CanBeImmediateIndex(index(), class_id()) | 942 locs->set_in(1, CanBeImmediateIndex(index(), class_id()) |
940 ? Location::RegisterOrSmiConstant(index()) | 943 ? Location::RegisterOrSmiConstant(index()) |
941 : Location::RequiresRegister()); | 944 : Location::RequiresRegister()); |
942 locs->set_out(Location::RequiresRegister()); | 945 locs->set_out(Location::RequiresRegister()); |
943 return locs; | 946 return locs; |
944 } | 947 } |
945 | 948 |
946 | 949 |
947 void StringCharCodeAtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 950 void StringCharCodeAtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
948 Register str = locs()->in(0).reg(); | 951 Register str = locs()->in(0).reg(); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
998 Symbols::kNullCharCodeSymbolOffset * kWordSize)); | 1001 Symbols::kNullCharCodeSymbolOffset * kWordSize)); |
999 } | 1002 } |
1000 | 1003 |
1001 | 1004 |
1002 LocationSummary* LoadIndexedInstr::MakeLocationSummary() const { | 1005 LocationSummary* LoadIndexedInstr::MakeLocationSummary() const { |
1003 const intptr_t kNumInputs = 2; | 1006 const intptr_t kNumInputs = 2; |
1004 const intptr_t kNumTemps = 0; | 1007 const intptr_t kNumTemps = 0; |
1005 LocationSummary* locs = | 1008 LocationSummary* locs = |
1006 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1009 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1007 locs->set_in(0, Location::RequiresRegister()); | 1010 locs->set_in(0, Location::RequiresRegister()); |
| 1011 // The smi index is either untagged and tagged again at the end of the |
| 1012 // operation (element size == 1), or it is left smi tagged (for all element |
| 1013 // sizes > 1). |
1008 locs->set_in(1, CanBeImmediateIndex(index(), class_id()) | 1014 locs->set_in(1, CanBeImmediateIndex(index(), class_id()) |
1009 ? Location::RegisterOrSmiConstant(index()) | 1015 ? Location::RegisterOrSmiConstant(index()) |
1010 : Location::RequiresRegister()); | 1016 : Location::RequiresRegister()); |
1011 if (representation() == kUnboxedDouble) { | 1017 if (representation() == kUnboxedDouble) { |
1012 locs->set_out(Location::RequiresXmmRegister()); | 1018 locs->set_out(Location::RequiresXmmRegister()); |
1013 } else { | 1019 } else { |
1014 locs->set_out(Location::RequiresRegister()); | 1020 locs->set_out(Location::RequiresRegister()); |
1015 } | 1021 } |
1016 return locs; | 1022 return locs; |
1017 } | 1023 } |
1018 | 1024 |
1019 | 1025 |
1020 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1026 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1021 Register array = locs()->in(0).reg(); | 1027 Register array = locs()->in(0).reg(); |
1022 Location index = locs()->in(1); | 1028 Location index = locs()->in(1); |
1023 | 1029 |
1024 if (class_id() == kExternalUint8ArrayCid) { | 1030 if (class_id() == kExternalUint8ArrayCid) { |
1025 Register result = locs()->out().reg(); | 1031 Register result = locs()->out().reg(); |
1026 Address element_address = index.IsRegister() | 1032 Address element_address = index.IsRegister() |
1027 ? Address(result, index.reg(), TIMES_1, 0) | 1033 ? FlowGraphCompiler::ExternalElementAddressForRegIndex( |
1028 : Address(result, Smi::Cast(index.constant()).Value()); | 1034 class_id(), result, index.reg()) |
| 1035 : FlowGraphCompiler::ExternalElementAddressForIntIndex( |
| 1036 class_id(), result, Smi::Cast(index.constant()).Value()); |
1029 if (index.IsRegister()) { | 1037 if (index.IsRegister()) { |
1030 __ SmiUntag(index.reg()); | 1038 __ SmiUntag(index.reg()); |
1031 } | 1039 } |
1032 __ movq(result, | 1040 __ movq(result, |
1033 FieldAddress(array, ExternalUint8Array::external_data_offset())); | 1041 FieldAddress(array, ExternalUint8Array::external_data_offset())); |
1034 __ movq(result, | 1042 __ movq(result, |
1035 Address(result, ExternalByteArrayData<uint8_t>::data_offset())); | 1043 Address(result, ExternalByteArrayData<uint8_t>::data_offset())); |
1036 __ movzxb(result, element_address); | 1044 __ movzxb(result, element_address); |
1037 __ SmiTag(result); | 1045 __ SmiTag(result); |
1038 if (index.IsRegister()) { | 1046 if (index.IsRegister()) { |
(...skipping 16 matching lines...) Expand all Loading... |
1055 // Promote to double. | 1063 // Promote to double. |
1056 __ cvtss2sd(result, locs()->out().xmm_reg()); | 1064 __ cvtss2sd(result, locs()->out().xmm_reg()); |
1057 } else { | 1065 } else { |
1058 ASSERT(class_id() == kFloat64ArrayCid); | 1066 ASSERT(class_id() == kFloat64ArrayCid); |
1059 __ movsd(result, element_address); | 1067 __ movsd(result, element_address); |
1060 } | 1068 } |
1061 return; | 1069 return; |
1062 } | 1070 } |
1063 | 1071 |
1064 Register result = locs()->out().reg(); | 1072 Register result = locs()->out().reg(); |
1065 if ((class_id() == kUint8ArrayCid) || | 1073 switch (class_id()) { |
1066 (class_id() == kUint8ClampedArrayCid)) { | 1074 case kInt8ArrayCid: |
1067 if (index.IsRegister()) { | 1075 case kUint8ArrayCid: |
1068 __ SmiUntag(index.reg()); | 1076 case kUint8ClampedArrayCid: |
1069 } | 1077 if (index.IsRegister()) { |
1070 __ movzxb(result, element_address); | 1078 __ SmiUntag(index.reg()); |
1071 __ SmiTag(result); | 1079 } |
1072 if (index.IsRegister()) { | 1080 if (class_id() == kInt8ArrayCid) { |
1073 __ SmiTag(index.reg()); // Re-tag. | 1081 __ movsxb(result, element_address); |
1074 } | 1082 } else { |
1075 return; | 1083 __ movzxb(result, element_address); |
| 1084 } |
| 1085 __ SmiTag(result); |
| 1086 if (index.IsRegister()) { |
| 1087 __ SmiTag(index.reg()); // Re-tag. |
| 1088 } |
| 1089 break; |
| 1090 case kInt16ArrayCid: |
| 1091 __ movsxw(result, element_address); |
| 1092 __ SmiTag(result); |
| 1093 break; |
| 1094 case kUint16ArrayCid: |
| 1095 __ movzxw(result, element_address); |
| 1096 __ SmiTag(result); |
| 1097 break; |
| 1098 default: |
| 1099 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); |
| 1100 __ movq(result, element_address); |
| 1101 break; |
1076 } | 1102 } |
1077 | |
1078 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); | |
1079 __ movq(result, element_address); | |
1080 } | 1103 } |
1081 | 1104 |
1082 | 1105 |
1083 LocationSummary* StoreIndexedInstr::MakeLocationSummary() const { | 1106 LocationSummary* StoreIndexedInstr::MakeLocationSummary() const { |
1084 const intptr_t kNumInputs = 3; | 1107 const intptr_t kNumInputs = 3; |
1085 const intptr_t numTemps = 0; | 1108 const intptr_t kNumTemps = 0; |
1086 LocationSummary* locs = | 1109 LocationSummary* locs = |
1087 new LocationSummary(kNumInputs, numTemps, LocationSummary::kNoCall); | 1110 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1111 // The smi index is either untagged and tagged again at the end of the |
| 1112 // operation (element size == 1), or it is left smi tagged (for all element |
| 1113 // sizes > 1). |
1088 locs->set_in(0, Location::RequiresRegister()); | 1114 locs->set_in(0, Location::RequiresRegister()); |
1089 locs->set_in(1, CanBeImmediateIndex(index(), class_id()) | 1115 locs->set_in(1, CanBeImmediateIndex(index(), class_id()) |
1090 ? Location::RegisterOrSmiConstant(index()) | 1116 ? Location::RegisterOrSmiConstant(index()) |
1091 : Location::RequiresRegister()); | 1117 : Location::RequiresRegister()); |
1092 switch (class_id()) { | 1118 switch (class_id()) { |
1093 case kArrayCid: | 1119 case kArrayCid: |
1094 locs->set_in(2, ShouldEmitStoreBarrier() | 1120 locs->set_in(2, ShouldEmitStoreBarrier() |
1095 ? Location::WritableRegister() | 1121 ? Location::WritableRegister() |
1096 : Location::RegisterOrConstant(value())); | 1122 : Location::RegisterOrConstant(value())); |
1097 break; | 1123 break; |
| 1124 case kInt8ArrayCid: |
1098 case kUint8ArrayCid: | 1125 case kUint8ArrayCid: |
| 1126 case kUint8ClampedArrayCid: |
1099 // TODO(fschneider): Add location constraint for byte registers (RAX, | 1127 // TODO(fschneider): Add location constraint for byte registers (RAX, |
1100 // RBX, RCX, RDX) instead of using a fixed register. | 1128 // RBX, RCX, RDX) instead of using a fixed register. |
1101 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), RAX)); | 1129 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), RAX)); |
1102 break; | 1130 break; |
| 1131 case kInt16ArrayCid: |
| 1132 case kUint16ArrayCid: |
| 1133 // Writable register because the value must be untagged before storing. |
| 1134 locs->set_in(2, Location::WritableRegister()); |
| 1135 break; |
1103 case kFloat32ArrayCid: | 1136 case kFloat32ArrayCid: |
1104 // Need temp register for float-to-double conversion. | 1137 // Need temp register for float-to-double conversion. |
1105 locs->AddTemp(Location::RequiresXmmRegister()); | 1138 locs->AddTemp(Location::RequiresXmmRegister()); |
1106 // Fall through. | 1139 // Fall through. |
1107 case kFloat64ArrayCid: | 1140 case kFloat64ArrayCid: |
1108 // TODO(srdjan): Support Float64 constants. | 1141 // TODO(srdjan): Support Float64 constants. |
1109 locs->set_in(2, Location::RequiresXmmRegister()); | 1142 locs->set_in(2, Location::RequiresXmmRegister()); |
1110 break; | 1143 break; |
1111 default: | 1144 default: |
1112 UNREACHABLE(); | 1145 UNREACHABLE(); |
(...skipping 19 matching lines...) Expand all Loading... |
1132 Register value = locs()->in(2).reg(); | 1165 Register value = locs()->in(2).reg(); |
1133 __ StoreIntoObject(array, element_address, value); | 1166 __ StoreIntoObject(array, element_address, value); |
1134 } else if (locs()->in(2).IsConstant()) { | 1167 } else if (locs()->in(2).IsConstant()) { |
1135 const Object& constant = locs()->in(2).constant(); | 1168 const Object& constant = locs()->in(2).constant(); |
1136 __ StoreObject(element_address, constant); | 1169 __ StoreObject(element_address, constant); |
1137 } else { | 1170 } else { |
1138 Register value = locs()->in(2).reg(); | 1171 Register value = locs()->in(2).reg(); |
1139 __ StoreIntoObjectNoBarrier(array, element_address, value); | 1172 __ StoreIntoObjectNoBarrier(array, element_address, value); |
1140 } | 1173 } |
1141 break; | 1174 break; |
| 1175 case kInt8ArrayCid: |
1142 case kUint8ArrayCid: | 1176 case kUint8ArrayCid: |
1143 if (index.IsRegister()) { | 1177 if (index.IsRegister()) { |
1144 __ SmiUntag(index.reg()); | 1178 __ SmiUntag(index.reg()); |
1145 } | 1179 } |
1146 if (locs()->in(2).IsConstant()) { | 1180 if (locs()->in(2).IsConstant()) { |
1147 const Smi& constant = Smi::Cast(locs()->in(2).constant()); | 1181 const Smi& constant = Smi::Cast(locs()->in(2).constant()); |
1148 __ movb(element_address, | 1182 __ movb(element_address, |
1149 Immediate(static_cast<int8_t>(constant.Value()))); | 1183 Immediate(static_cast<int8_t>(constant.Value()))); |
1150 } else { | 1184 } else { |
1151 ASSERT(locs()->in(2).reg() == RAX); | 1185 ASSERT(locs()->in(2).reg() == RAX); |
1152 __ SmiUntag(RAX); | 1186 __ SmiUntag(RAX); |
1153 __ movb(element_address, RAX); | 1187 __ movb(element_address, RAX); |
1154 } | 1188 } |
1155 if (index.IsRegister()) { | 1189 if (index.IsRegister()) { |
1156 __ SmiTag(index.reg()); // Re-tag. | 1190 __ SmiTag(index.reg()); // Re-tag. |
1157 } | 1191 } |
1158 break; | 1192 break; |
| 1193 case kUint8ClampedArrayCid: { |
| 1194 if (index.IsRegister()) { |
| 1195 __ SmiUntag(index.reg()); |
| 1196 } |
| 1197 if (locs()->in(2).IsConstant()) { |
| 1198 const Smi& constant = Smi::Cast(locs()->in(2).constant()); |
| 1199 intptr_t value = constant.Value(); |
| 1200 // Clamp to 0x0 or 0xFF respectively. |
| 1201 if (value > 0xFF) { |
| 1202 value = 0xFF; |
| 1203 } else if (value < 0) { |
| 1204 value = 0; |
| 1205 } |
| 1206 __ movb(element_address, |
| 1207 Immediate(static_cast<int8_t>(value))); |
| 1208 } else { |
| 1209 ASSERT(locs()->in(2).reg() == RAX); |
| 1210 Label store_value, store_0xff; |
| 1211 __ SmiUntag(RAX); |
| 1212 __ cmpq(RAX, Immediate(0xFF)); |
| 1213 __ j(BELOW_EQUAL, &store_value, Assembler::kNearJump); |
| 1214 // Clamp to 0x0 or 0xFF respectively. |
| 1215 __ j(GREATER, &store_0xff); |
| 1216 __ xorq(RAX, RAX); |
| 1217 __ jmp(&store_value, Assembler::kNearJump); |
| 1218 __ Bind(&store_0xff); |
| 1219 __ movq(RAX, Immediate(0xFF)); |
| 1220 __ Bind(&store_value); |
| 1221 __ movb(element_address, RAX); |
| 1222 } |
| 1223 if (index.IsRegister()) { |
| 1224 __ SmiTag(index.reg()); // Re-tag. |
| 1225 } |
| 1226 break; |
| 1227 } |
| 1228 case kInt16ArrayCid: |
| 1229 case kUint16ArrayCid: { |
| 1230 Register value = locs()->in(2).reg(); |
| 1231 __ SmiUntag(value); |
| 1232 __ movw(element_address, value); |
| 1233 break; |
| 1234 } |
1159 case kFloat32ArrayCid: | 1235 case kFloat32ArrayCid: |
1160 // Convert to single precision. | 1236 // Convert to single precision. |
1161 __ cvtsd2ss(locs()->temp(0).xmm_reg(), locs()->in(2).xmm_reg()); | 1237 __ cvtsd2ss(locs()->temp(0).xmm_reg(), locs()->in(2).xmm_reg()); |
1162 // Store. | 1238 // Store. |
1163 __ movss(element_address, locs()->temp(0).xmm_reg()); | 1239 __ movss(element_address, locs()->temp(0).xmm_reg()); |
1164 break; | 1240 break; |
1165 case kFloat64ArrayCid: | 1241 case kFloat64ArrayCid: |
1166 __ movsd(element_address, locs()->in(2).xmm_reg()); | 1242 __ movsd(element_address, locs()->in(2).xmm_reg()); |
1167 break; | 1243 break; |
1168 default: | 1244 default: |
(...skipping 1335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2504 | 2580 |
2505 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2581 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2506 UNIMPLEMENTED(); | 2582 UNIMPLEMENTED(); |
2507 } | 2583 } |
2508 | 2584 |
2509 } // namespace dart | 2585 } // namespace dart |
2510 | 2586 |
2511 #undef __ | 2587 #undef __ |
2512 | 2588 |
2513 #endif // defined TARGET_ARCH_X64 | 2589 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |