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 1006 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1017 } | 1017 } |
1018 | 1018 |
1019 | 1019 |
1020 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1020 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1021 Register array = locs()->in(0).reg(); | 1021 Register array = locs()->in(0).reg(); |
1022 Location index = locs()->in(1); | 1022 Location index = locs()->in(1); |
1023 | 1023 |
1024 if (class_id() == kExternalUint8ArrayCid) { | 1024 if (class_id() == kExternalUint8ArrayCid) { |
1025 Register result = locs()->out().reg(); | 1025 Register result = locs()->out().reg(); |
1026 Address element_address = index.IsRegister() | 1026 Address element_address = index.IsRegister() |
1027 ? Address(result, index.reg(), TIMES_1, 0) | 1027 ? FlowGraphCompiler::ExternalElementAddressForRegIndex( |
1028 : Address(result, Smi::Cast(index.constant()).Value()); | 1028 class_id(), result, index.reg()) |
| 1029 : FlowGraphCompiler::ExternalElementAddressForIntIndex( |
| 1030 class_id(), result, Smi::Cast(index.constant()).Value()); |
1029 if (index.IsRegister()) { | 1031 if (index.IsRegister()) { |
1030 __ SmiUntag(index.reg()); | 1032 __ SmiUntag(index.reg()); |
1031 } | 1033 } |
1032 __ movq(result, | 1034 __ movq(result, |
1033 FieldAddress(array, ExternalUint8Array::external_data_offset())); | 1035 FieldAddress(array, ExternalUint8Array::external_data_offset())); |
1034 __ movq(result, | 1036 __ movq(result, |
1035 Address(result, ExternalByteArrayData<uint8_t>::data_offset())); | 1037 Address(result, ExternalByteArrayData<uint8_t>::data_offset())); |
1036 __ movzxb(result, element_address); | 1038 __ movzxb(result, element_address); |
1037 __ SmiTag(result); | 1039 __ SmiTag(result); |
1038 if (index.IsRegister()) { | 1040 if (index.IsRegister()) { |
(...skipping 16 matching lines...) Expand all Loading... |
1055 // Promote to double. | 1057 // Promote to double. |
1056 __ cvtss2sd(result, locs()->out().xmm_reg()); | 1058 __ cvtss2sd(result, locs()->out().xmm_reg()); |
1057 } else { | 1059 } else { |
1058 ASSERT(class_id() == kFloat64ArrayCid); | 1060 ASSERT(class_id() == kFloat64ArrayCid); |
1059 __ movsd(result, element_address); | 1061 __ movsd(result, element_address); |
1060 } | 1062 } |
1061 return; | 1063 return; |
1062 } | 1064 } |
1063 | 1065 |
1064 Register result = locs()->out().reg(); | 1066 Register result = locs()->out().reg(); |
1065 if ((class_id() == kUint8ArrayCid) || | 1067 switch (class_id()) { |
1066 (class_id() == kUint8ClampedArrayCid)) { | 1068 case kInt8ArrayCid: |
1067 if (index.IsRegister()) { | 1069 case kUint8ArrayCid: |
1068 __ SmiUntag(index.reg()); | 1070 case kUint8ClampedArrayCid: |
1069 } | 1071 if (index.IsRegister()) { |
1070 __ movzxb(result, element_address); | 1072 __ SmiUntag(index.reg()); |
1071 __ SmiTag(result); | 1073 } |
1072 if (index.IsRegister()) { | 1074 if (class_id() == kInt8ArrayCid) { |
1073 __ SmiTag(index.reg()); // Re-tag. | 1075 __ movsxb(result, element_address); |
1074 } | 1076 } else { |
1075 return; | 1077 __ movzxb(result, element_address); |
| 1078 } |
| 1079 __ SmiTag(result); |
| 1080 if (index.IsRegister()) { |
| 1081 __ SmiTag(index.reg()); // Re-tag. |
| 1082 } |
| 1083 break; |
| 1084 case kInt16ArrayCid: |
| 1085 __ movsxw(result, element_address); |
| 1086 __ SmiTag(result); |
| 1087 break; |
| 1088 case kUint16ArrayCid: |
| 1089 __ movzxw(result, element_address); |
| 1090 __ SmiTag(result); |
| 1091 break; |
| 1092 default: |
| 1093 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); |
| 1094 __ movq(result, element_address); |
| 1095 break; |
1076 } | 1096 } |
1077 | |
1078 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); | |
1079 __ movq(result, element_address); | |
1080 } | 1097 } |
1081 | 1098 |
1082 | 1099 |
1083 LocationSummary* StoreIndexedInstr::MakeLocationSummary() const { | 1100 LocationSummary* StoreIndexedInstr::MakeLocationSummary() const { |
1084 const intptr_t kNumInputs = 3; | 1101 const intptr_t kNumInputs = 3; |
1085 const intptr_t numTemps = 0; | 1102 const intptr_t kNumTemps = 0; |
1086 LocationSummary* locs = | 1103 LocationSummary* locs = |
1087 new LocationSummary(kNumInputs, numTemps, LocationSummary::kNoCall); | 1104 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1088 locs->set_in(0, Location::RequiresRegister()); | 1105 locs->set_in(0, Location::RequiresRegister()); |
1089 locs->set_in(1, CanBeImmediateIndex(index(), class_id()) | 1106 locs->set_in(1, CanBeImmediateIndex(index(), class_id()) |
1090 ? Location::RegisterOrSmiConstant(index()) | 1107 ? Location::RegisterOrSmiConstant(index()) |
1091 : Location::RequiresRegister()); | 1108 : Location::RequiresRegister()); |
1092 switch (class_id()) { | 1109 switch (class_id()) { |
1093 case kArrayCid: | 1110 case kArrayCid: |
1094 locs->set_in(2, ShouldEmitStoreBarrier() | 1111 locs->set_in(2, ShouldEmitStoreBarrier() |
1095 ? Location::WritableRegister() | 1112 ? Location::WritableRegister() |
1096 : Location::RegisterOrConstant(value())); | 1113 : Location::RegisterOrConstant(value())); |
1097 break; | 1114 break; |
| 1115 case kInt8ArrayCid: |
1098 case kUint8ArrayCid: | 1116 case kUint8ArrayCid: |
| 1117 case kUint8ClampedArrayCid: |
1099 // TODO(fschneider): Add location constraint for byte registers (RAX, | 1118 // TODO(fschneider): Add location constraint for byte registers (RAX, |
1100 // RBX, RCX, RDX) instead of using a fixed register. | 1119 // RBX, RCX, RDX) instead of using a fixed register. |
1101 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), RAX)); | 1120 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), RAX)); |
1102 break; | 1121 break; |
| 1122 case kInt16ArrayCid: |
| 1123 case kUint16ArrayCid: |
| 1124 // TODO(fschneider): Support int16/uint16 constants. |
| 1125 locs->set_in(2, Location::WritableRegister()); |
| 1126 break; |
1103 case kFloat32ArrayCid: | 1127 case kFloat32ArrayCid: |
1104 // Need temp register for float-to-double conversion. | 1128 // Need temp register for float-to-double conversion. |
1105 locs->AddTemp(Location::RequiresXmmRegister()); | 1129 locs->AddTemp(Location::RequiresXmmRegister()); |
1106 // Fall through. | 1130 // Fall through. |
1107 case kFloat64ArrayCid: | 1131 case kFloat64ArrayCid: |
1108 // TODO(srdjan): Support Float64 constants. | 1132 // TODO(srdjan): Support Float64 constants. |
1109 locs->set_in(2, Location::RequiresXmmRegister()); | 1133 locs->set_in(2, Location::RequiresXmmRegister()); |
1110 break; | 1134 break; |
1111 default: | 1135 default: |
1112 UNREACHABLE(); | 1136 UNREACHABLE(); |
(...skipping 19 matching lines...) Expand all Loading... |
1132 Register value = locs()->in(2).reg(); | 1156 Register value = locs()->in(2).reg(); |
1133 __ StoreIntoObject(array, element_address, value); | 1157 __ StoreIntoObject(array, element_address, value); |
1134 } else if (locs()->in(2).IsConstant()) { | 1158 } else if (locs()->in(2).IsConstant()) { |
1135 const Object& constant = locs()->in(2).constant(); | 1159 const Object& constant = locs()->in(2).constant(); |
1136 __ StoreObject(element_address, constant); | 1160 __ StoreObject(element_address, constant); |
1137 } else { | 1161 } else { |
1138 Register value = locs()->in(2).reg(); | 1162 Register value = locs()->in(2).reg(); |
1139 __ StoreIntoObjectNoBarrier(array, element_address, value); | 1163 __ StoreIntoObjectNoBarrier(array, element_address, value); |
1140 } | 1164 } |
1141 break; | 1165 break; |
| 1166 case kInt8ArrayCid: |
1142 case kUint8ArrayCid: | 1167 case kUint8ArrayCid: |
1143 if (index.IsRegister()) { | 1168 if (index.IsRegister()) { |
1144 __ SmiUntag(index.reg()); | 1169 __ SmiUntag(index.reg()); |
1145 } | 1170 } |
1146 if (locs()->in(2).IsConstant()) { | 1171 if (locs()->in(2).IsConstant()) { |
1147 const Smi& constant = Smi::Cast(locs()->in(2).constant()); | 1172 const Smi& constant = Smi::Cast(locs()->in(2).constant()); |
1148 __ movb(element_address, | 1173 __ movb(element_address, |
1149 Immediate(static_cast<int8_t>(constant.Value()))); | 1174 Immediate(static_cast<int8_t>(constant.Value()))); |
1150 } else { | 1175 } else { |
1151 ASSERT(locs()->in(2).reg() == RAX); | 1176 ASSERT(locs()->in(2).reg() == RAX); |
1152 __ SmiUntag(RAX); | 1177 __ SmiUntag(RAX); |
1153 __ movb(element_address, RAX); | 1178 __ movb(element_address, RAX); |
1154 } | 1179 } |
1155 if (index.IsRegister()) { | 1180 if (index.IsRegister()) { |
1156 __ SmiTag(index.reg()); // Re-tag. | 1181 __ SmiTag(index.reg()); // Re-tag. |
1157 } | 1182 } |
1158 break; | 1183 break; |
| 1184 case kUint8ClampedArrayCid: { |
| 1185 if (index.IsRegister()) { |
| 1186 __ SmiUntag(index.reg()); |
| 1187 } |
| 1188 if (locs()->in(2).IsConstant()) { |
| 1189 const Smi& constant = Smi::Cast(locs()->in(2).constant()); |
| 1190 intptr_t value = constant.Value(); |
| 1191 // Clamp to 0x0 or 0xFF respectively. |
| 1192 if (value > 0xFF) { |
| 1193 value = 0xFF; |
| 1194 } else if (value < 0) { |
| 1195 value = 0; |
| 1196 } |
| 1197 __ movb(element_address, |
| 1198 Immediate(static_cast<int8_t>(value))); |
| 1199 } else { |
| 1200 ASSERT(locs()->in(2).reg() == RAX); |
| 1201 Label store_value, store_0xff; |
| 1202 __ SmiUntag(RAX); |
| 1203 __ cmpq(RAX, Immediate(0xFF)); |
| 1204 __ j(BELOW_EQUAL, &store_value, Assembler::kNearJump); |
| 1205 // Clamp to 0x0 or 0xFF respectively. |
| 1206 __ j(GREATER, &store_0xff); |
| 1207 __ xorq(RAX, RAX); |
| 1208 __ jmp(&store_value, Assembler::kNearJump); |
| 1209 __ Bind(&store_0xff); |
| 1210 __ movq(RAX, Immediate(0xFF)); |
| 1211 __ Bind(&store_value); |
| 1212 __ movb(element_address, RAX); |
| 1213 } |
| 1214 if (index.IsRegister()) { |
| 1215 __ SmiTag(index.reg()); // Re-tag. |
| 1216 } |
| 1217 break; |
| 1218 } |
| 1219 case kInt16ArrayCid: |
| 1220 case kUint16ArrayCid: { |
| 1221 Register value = locs()->in(2).reg(); |
| 1222 __ SmiUntag(value); |
| 1223 __ movw(element_address, value); |
| 1224 break; |
| 1225 } |
1159 case kFloat32ArrayCid: | 1226 case kFloat32ArrayCid: |
1160 // Convert to single precision. | 1227 // Convert to single precision. |
1161 __ cvtsd2ss(locs()->temp(0).xmm_reg(), locs()->in(2).xmm_reg()); | 1228 __ cvtsd2ss(locs()->temp(0).xmm_reg(), locs()->in(2).xmm_reg()); |
1162 // Store. | 1229 // Store. |
1163 __ movss(element_address, locs()->temp(0).xmm_reg()); | 1230 __ movss(element_address, locs()->temp(0).xmm_reg()); |
1164 break; | 1231 break; |
1165 case kFloat64ArrayCid: | 1232 case kFloat64ArrayCid: |
1166 __ movsd(element_address, locs()->in(2).xmm_reg()); | 1233 __ movsd(element_address, locs()->in(2).xmm_reg()); |
1167 break; | 1234 break; |
1168 default: | 1235 default: |
(...skipping 1335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2504 | 2571 |
2505 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2572 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2506 UNIMPLEMENTED(); | 2573 UNIMPLEMENTED(); |
2507 } | 2574 } |
2508 | 2575 |
2509 } // namespace dart | 2576 } // namespace dart |
2510 | 2577 |
2511 #undef __ | 2578 #undef __ |
2512 | 2579 |
2513 #endif // defined TARGET_ARCH_X64 | 2580 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |