OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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_ARM64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64. |
6 #if defined(TARGET_ARCH_ARM64) | 6 #if defined(TARGET_ARCH_ARM64) |
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 830 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
841 token_pos(), | 841 token_pos(), |
842 CallFunction(), | 842 CallFunction(), |
843 kNumberOfArguments, | 843 kNumberOfArguments, |
844 kNoArgumentNames, | 844 kNoArgumentNames, |
845 locs()); | 845 locs()); |
846 ASSERT(locs()->out(0).reg() == R0); | 846 ASSERT(locs()->out(0).reg() == R0); |
847 } | 847 } |
848 | 848 |
849 | 849 |
850 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(bool opt) const { | 850 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(bool opt) const { |
851 UNIMPLEMENTED(); | 851 const intptr_t kNumInputs = 1; |
852 return NULL; | 852 return LocationSummary::Make(kNumInputs, |
| 853 Location::RequiresRegister(), |
| 854 LocationSummary::kNoCall); |
853 } | 855 } |
854 | 856 |
855 | 857 |
856 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 858 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
857 UNIMPLEMENTED(); | 859 Register object = locs()->in(0).reg(); |
| 860 Register result = locs()->out(0).reg(); |
| 861 __ LoadFieldFromOffset(result, object, offset(), PP); |
858 } | 862 } |
859 | 863 |
860 | 864 |
861 LocationSummary* LoadClassIdInstr::MakeLocationSummary(bool opt) const { | 865 LocationSummary* LoadClassIdInstr::MakeLocationSummary(bool opt) const { |
862 const intptr_t kNumInputs = 1; | 866 const intptr_t kNumInputs = 1; |
863 return LocationSummary::Make(kNumInputs, | 867 return LocationSummary::Make(kNumInputs, |
864 Location::RequiresRegister(), | 868 Location::RequiresRegister(), |
865 LocationSummary::kNoCall); | 869 LocationSummary::kNoCall); |
866 } | 870 } |
867 | 871 |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1006 } | 1010 } |
1007 | 1011 |
1008 if (!IsExternal()) { | 1012 if (!IsExternal()) { |
1009 ASSERT(this->array()->definition()->representation() == kTagged); | 1013 ASSERT(this->array()->definition()->representation() == kTagged); |
1010 __ AddImmediate(index.reg(), index.reg(), | 1014 __ AddImmediate(index.reg(), index.reg(), |
1011 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag, PP); | 1015 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag, PP); |
1012 } | 1016 } |
1013 element_address = Address(array, index.reg(), UXTX, Address::Unscaled); | 1017 element_address = Address(array, index.reg(), UXTX, Address::Unscaled); |
1014 | 1018 |
1015 if ((representation() == kUnboxedDouble) || | 1019 if ((representation() == kUnboxedDouble) || |
1016 (representation() == kUnboxedMint) || | |
1017 (representation() == kUnboxedFloat32x4) || | 1020 (representation() == kUnboxedFloat32x4) || |
1018 (representation() == kUnboxedInt32x4) || | 1021 (representation() == kUnboxedInt32x4) || |
1019 (representation() == kUnboxedFloat64x2)) { | 1022 (representation() == kUnboxedFloat64x2)) { |
1020 const VRegister result = locs()->out(0).fpu_reg(); | 1023 const VRegister result = locs()->out(0).fpu_reg(); |
1021 switch (class_id()) { | 1024 switch (class_id()) { |
1022 case kTypedDataInt32ArrayCid: | |
1023 case kTypedDataUint32ArrayCid: | |
1024 // TODO(zra): Add when we have simd. | |
1025 UNIMPLEMENTED(); | |
1026 break; | |
1027 case kTypedDataFloat32ArrayCid: | 1025 case kTypedDataFloat32ArrayCid: |
1028 // Load single precision float. | 1026 // Load single precision float. |
1029 __ fldrs(result, element_address); | 1027 __ fldrs(result, element_address); |
1030 break; | 1028 break; |
1031 case kTypedDataFloat64ArrayCid: | 1029 case kTypedDataFloat64ArrayCid: |
1032 // Load double precision float. | 1030 // Load double precision float. |
1033 __ fldrd(result, element_address); | 1031 __ fldrd(result, element_address); |
1034 break; | 1032 break; |
1035 case kTypedDataFloat64x2ArrayCid: | 1033 case kTypedDataFloat64x2ArrayCid: |
1036 case kTypedDataInt32x4ArrayCid: | 1034 case kTypedDataInt32x4ArrayCid: |
1037 case kTypedDataFloat32x4ArrayCid: | 1035 case kTypedDataFloat32x4ArrayCid: |
1038 // TODO(zra): Add when we have simd. | 1036 __ fldrq(result, element_address); |
1039 UNIMPLEMENTED(); | |
1040 break; | 1037 break; |
1041 } | 1038 } |
1042 return; | 1039 return; |
1043 } | 1040 } |
1044 | 1041 |
1045 Register result = locs()->out(0).reg(); | 1042 Register result = locs()->out(0).reg(); |
1046 switch (class_id()) { | 1043 switch (class_id()) { |
1047 case kTypedDataInt8ArrayCid: | 1044 case kTypedDataInt8ArrayCid: |
1048 ASSERT(index_scale() == 1); | 1045 ASSERT(index_scale() == 1); |
1049 __ ldr(result, element_address, kByte); | 1046 __ ldr(result, element_address, kByte); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1092 switch (class_id_) { | 1089 switch (class_id_) { |
1093 case kArrayCid: | 1090 case kArrayCid: |
1094 case kOneByteStringCid: | 1091 case kOneByteStringCid: |
1095 case kTypedDataInt8ArrayCid: | 1092 case kTypedDataInt8ArrayCid: |
1096 case kTypedDataUint8ArrayCid: | 1093 case kTypedDataUint8ArrayCid: |
1097 case kExternalTypedDataUint8ArrayCid: | 1094 case kExternalTypedDataUint8ArrayCid: |
1098 case kTypedDataUint8ClampedArrayCid: | 1095 case kTypedDataUint8ClampedArrayCid: |
1099 case kExternalTypedDataUint8ClampedArrayCid: | 1096 case kExternalTypedDataUint8ClampedArrayCid: |
1100 case kTypedDataInt16ArrayCid: | 1097 case kTypedDataInt16ArrayCid: |
1101 case kTypedDataUint16ArrayCid: | 1098 case kTypedDataUint16ArrayCid: |
1102 return kTagged; | |
1103 case kTypedDataInt32ArrayCid: | 1099 case kTypedDataInt32ArrayCid: |
1104 case kTypedDataUint32ArrayCid: | 1100 case kTypedDataUint32ArrayCid: |
1105 return value()->IsSmiValue() ? kTagged : kUnboxedMint; | 1101 return kTagged; |
1106 case kTypedDataFloat32ArrayCid: | 1102 case kTypedDataFloat32ArrayCid: |
1107 case kTypedDataFloat64ArrayCid: | 1103 case kTypedDataFloat64ArrayCid: |
1108 return kUnboxedDouble; | 1104 return kUnboxedDouble; |
1109 case kTypedDataFloat32x4ArrayCid: | 1105 case kTypedDataFloat32x4ArrayCid: |
1110 return kUnboxedFloat32x4; | 1106 return kUnboxedFloat32x4; |
1111 case kTypedDataInt32x4ArrayCid: | 1107 case kTypedDataInt32x4ArrayCid: |
1112 return kUnboxedInt32x4; | 1108 return kUnboxedInt32x4; |
1113 case kTypedDataFloat64x2ArrayCid: | 1109 case kTypedDataFloat64x2ArrayCid: |
1114 return kUnboxedFloat64x2; | 1110 return kUnboxedFloat64x2; |
1115 default: | 1111 default: |
(...skipping 24 matching lines...) Expand all Loading... |
1140 case kTypedDataInt8ArrayCid: | 1136 case kTypedDataInt8ArrayCid: |
1141 case kTypedDataUint8ArrayCid: | 1137 case kTypedDataUint8ArrayCid: |
1142 case kTypedDataUint8ClampedArrayCid: | 1138 case kTypedDataUint8ClampedArrayCid: |
1143 case kOneByteStringCid: | 1139 case kOneByteStringCid: |
1144 case kTypedDataInt16ArrayCid: | 1140 case kTypedDataInt16ArrayCid: |
1145 case kTypedDataUint16ArrayCid: | 1141 case kTypedDataUint16ArrayCid: |
1146 locs->set_in(2, Location::WritableRegister()); | 1142 locs->set_in(2, Location::WritableRegister()); |
1147 break; | 1143 break; |
1148 case kTypedDataInt32ArrayCid: | 1144 case kTypedDataInt32ArrayCid: |
1149 case kTypedDataUint32ArrayCid: | 1145 case kTypedDataUint32ArrayCid: |
1150 // Mints are stored in Q registers. For smis, use a writable register | 1146 locs->set_in(2, Location::WritableRegister()); |
1151 // because the value must be untagged before storing. | |
1152 if (value()->IsSmiValue()) { | |
1153 locs->set_in(2, Location::WritableRegister()); | |
1154 } else { | |
1155 // TODO(zra): Implement when we add simd loads and stores. | |
1156 UNIMPLEMENTED(); | |
1157 } | |
1158 break; | 1147 break; |
1159 case kTypedDataFloat32ArrayCid: | 1148 case kTypedDataFloat32ArrayCid: |
1160 case kTypedDataFloat64ArrayCid: // TODO(srdjan): Support Float64 constants. | 1149 case kTypedDataFloat64ArrayCid: // TODO(srdjan): Support Float64 constants. |
1161 locs->set_in(2, Location::RequiresFpuRegister()); | 1150 locs->set_in(2, Location::RequiresFpuRegister()); |
1162 break; | 1151 break; |
1163 case kTypedDataInt32x4ArrayCid: | 1152 case kTypedDataInt32x4ArrayCid: |
1164 case kTypedDataFloat32x4ArrayCid: | 1153 case kTypedDataFloat32x4ArrayCid: |
1165 case kTypedDataFloat64x2ArrayCid: | 1154 case kTypedDataFloat64x2ArrayCid: |
1166 // TODO(zra): Implement when we add simd loads and stores. | 1155 locs->set_in(2, Location::RequiresFpuRegister()); |
1167 UNIMPLEMENTED(); | |
1168 break; | 1156 break; |
1169 default: | 1157 default: |
1170 UNREACHABLE(); | 1158 UNREACHABLE(); |
1171 return NULL; | 1159 return NULL; |
1172 } | 1160 } |
1173 return locs; | 1161 return locs; |
1174 } | 1162 } |
1175 | 1163 |
1176 | 1164 |
1177 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1165 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1273 } | 1261 } |
1274 case kTypedDataInt16ArrayCid: | 1262 case kTypedDataInt16ArrayCid: |
1275 case kTypedDataUint16ArrayCid: { | 1263 case kTypedDataUint16ArrayCid: { |
1276 const Register value = locs()->in(2).reg(); | 1264 const Register value = locs()->in(2).reg(); |
1277 __ SmiUntag(value); | 1265 __ SmiUntag(value); |
1278 __ str(value, element_address, kUnsignedHalfword); | 1266 __ str(value, element_address, kUnsignedHalfword); |
1279 break; | 1267 break; |
1280 } | 1268 } |
1281 case kTypedDataInt32ArrayCid: | 1269 case kTypedDataInt32ArrayCid: |
1282 case kTypedDataUint32ArrayCid: { | 1270 case kTypedDataUint32ArrayCid: { |
1283 if (value()->IsSmiValue()) { | 1271 const Register value = locs()->in(2).reg(); |
1284 ASSERT(RequiredInputRepresentation(2) == kTagged); | 1272 __ SmiUntag(value); |
1285 const Register value = locs()->in(2).reg(); | 1273 __ str(value, element_address, kUnsignedWord); |
1286 __ SmiUntag(value); | |
1287 __ str(value, element_address, kUnsignedWord); | |
1288 } else { | |
1289 // TODO(zra): Implement when we add simd loads and stores. | |
1290 UNIMPLEMENTED(); | |
1291 } | |
1292 break; | 1274 break; |
1293 } | 1275 } |
1294 case kTypedDataFloat32ArrayCid: { | 1276 case kTypedDataFloat32ArrayCid: { |
1295 const VRegister in2 = locs()->in(2).fpu_reg(); | 1277 const VRegister in2 = locs()->in(2).fpu_reg(); |
1296 __ add(index.reg(), index.reg(), Operand(array)); | 1278 __ add(index.reg(), index.reg(), Operand(array)); |
1297 __ fstrs(in2, Address(index.reg())); | 1279 __ fstrs(in2, Address(index.reg())); |
1298 break; | 1280 break; |
1299 } | 1281 } |
1300 case kTypedDataFloat64ArrayCid: { | 1282 case kTypedDataFloat64ArrayCid: { |
1301 const VRegister in2 = locs()->in(2).fpu_reg(); | 1283 const VRegister in2 = locs()->in(2).fpu_reg(); |
1302 __ add(index.reg(), index.reg(), Operand(array)); | 1284 __ add(index.reg(), index.reg(), Operand(array)); |
1303 __ StoreDToOffset(in2, index.reg(), 0, PP); | 1285 __ StoreDToOffset(in2, index.reg(), 0, PP); |
1304 break; | 1286 break; |
1305 } | 1287 } |
1306 case kTypedDataFloat64x2ArrayCid: | 1288 case kTypedDataFloat64x2ArrayCid: |
1307 case kTypedDataInt32x4ArrayCid: | 1289 case kTypedDataInt32x4ArrayCid: |
1308 case kTypedDataFloat32x4ArrayCid: { | 1290 case kTypedDataFloat32x4ArrayCid: { |
1309 // TODO(zra): Implement when we add simd loads and stores. | 1291 const VRegister in2 = locs()->in(2).fpu_reg(); |
1310 UNIMPLEMENTED(); | 1292 __ add(index.reg(), index.reg(), Operand(array)); |
| 1293 __ StoreQToOffset(in2, index.reg(), 0, PP); |
1311 break; | 1294 break; |
1312 } | 1295 } |
1313 default: | 1296 default: |
1314 UNREACHABLE(); | 1297 UNREACHABLE(); |
1315 } | 1298 } |
1316 } | 1299 } |
1317 | 1300 |
1318 | 1301 |
1319 static void LoadValueCid(FlowGraphCompiler* compiler, | 1302 static void LoadValueCid(FlowGraphCompiler* compiler, |
1320 Register value_cid_reg, | 1303 Register value_cid_reg, |
(...skipping 2132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3453 __ fmuld(result, val, val); | 3436 __ fmuld(result, val, val); |
3454 } else { | 3437 } else { |
3455 ASSERT((kind() == MathUnaryInstr::kSin) || | 3438 ASSERT((kind() == MathUnaryInstr::kSin) || |
3456 (kind() == MathUnaryInstr::kCos)); | 3439 (kind() == MathUnaryInstr::kCos)); |
3457 __ CallRuntime(TargetFunction(), InputCount()); | 3440 __ CallRuntime(TargetFunction(), InputCount()); |
3458 } | 3441 } |
3459 } | 3442 } |
3460 | 3443 |
3461 | 3444 |
3462 LocationSummary* MathMinMaxInstr::MakeLocationSummary(bool opt) const { | 3445 LocationSummary* MathMinMaxInstr::MakeLocationSummary(bool opt) const { |
3463 UNIMPLEMENTED(); | 3446 if (result_cid() == kDoubleCid) { |
3464 return NULL; | 3447 const intptr_t kNumInputs = 2; |
| 3448 const intptr_t kNumTemps = 0; |
| 3449 LocationSummary* summary = |
| 3450 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3451 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3452 summary->set_in(1, Location::RequiresFpuRegister()); |
| 3453 // Reuse the left register so that code can be made shorter. |
| 3454 summary->set_out(0, Location::SameAsFirstInput()); |
| 3455 return summary; |
| 3456 } |
| 3457 ASSERT(result_cid() == kSmiCid); |
| 3458 const intptr_t kNumInputs = 2; |
| 3459 const intptr_t kNumTemps = 0; |
| 3460 LocationSummary* summary = |
| 3461 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3462 summary->set_in(0, Location::RequiresRegister()); |
| 3463 summary->set_in(1, Location::RequiresRegister()); |
| 3464 // Reuse the left register so that code can be made shorter. |
| 3465 summary->set_out(0, Location::SameAsFirstInput()); |
| 3466 return summary; |
3465 } | 3467 } |
3466 | 3468 |
3467 | 3469 |
3468 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3470 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3469 UNIMPLEMENTED(); | 3471 ASSERT((op_kind() == MethodRecognizer::kMathMin) || |
| 3472 (op_kind() == MethodRecognizer::kMathMax)); |
| 3473 const intptr_t is_min = (op_kind() == MethodRecognizer::kMathMin); |
| 3474 if (result_cid() == kDoubleCid) { |
| 3475 Label done, returns_nan, are_equal; |
| 3476 const VRegister left = locs()->in(0).fpu_reg(); |
| 3477 const VRegister right = locs()->in(1).fpu_reg(); |
| 3478 const VRegister result = locs()->out(0).fpu_reg(); |
| 3479 __ fcmpd(left, right); |
| 3480 __ b(&returns_nan, VS); |
| 3481 __ b(&are_equal, EQ); |
| 3482 const Condition double_condition = |
| 3483 is_min ? TokenKindToDoubleCondition(Token::kLTE) |
| 3484 : TokenKindToDoubleCondition(Token::kGTE); |
| 3485 ASSERT(left == result); |
| 3486 __ b(&done, double_condition); |
| 3487 __ fmovdd(result, right); |
| 3488 __ b(&done); |
| 3489 |
| 3490 __ Bind(&returns_nan); |
| 3491 __ LoadDImmediate(result, NAN, PP); |
| 3492 __ b(&done); |
| 3493 |
| 3494 __ Bind(&are_equal); |
| 3495 // Check for negative zero: -0.0 is equal 0.0 but min or max must return |
| 3496 // -0.0 or 0.0 respectively. |
| 3497 // Check for negative left value (get the sign bit): |
| 3498 // - min -> left is negative ? left : right. |
| 3499 // - max -> left is negative ? right : left |
| 3500 // Check the sign bit. |
| 3501 __ fmovrd(TMP, left); // Sign bit is in bit 63 of TMP. |
| 3502 __ CompareImmediate(TMP, 0, PP); |
| 3503 if (is_min) { |
| 3504 ASSERT(left == result); |
| 3505 __ b(&done, LT); |
| 3506 __ fmovdd(result, right); |
| 3507 } else { |
| 3508 __ b(&done, GE); |
| 3509 __ fmovdd(result, right); |
| 3510 ASSERT(left == result); |
| 3511 } |
| 3512 __ Bind(&done); |
| 3513 return; |
| 3514 } |
| 3515 |
| 3516 ASSERT(result_cid() == kSmiCid); |
| 3517 Register left = locs()->in(0).reg(); |
| 3518 Register right = locs()->in(1).reg(); |
| 3519 Register result = locs()->out(0).reg(); |
| 3520 __ CompareRegisters(left, right); |
| 3521 ASSERT(result == left); |
| 3522 if (is_min) { |
| 3523 __ csel(result, right, left, GT); |
| 3524 } else { |
| 3525 __ csel(result, right, left, LT); |
| 3526 } |
3470 } | 3527 } |
3471 | 3528 |
3472 | 3529 |
3473 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(bool opt) const { | 3530 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(bool opt) const { |
3474 const intptr_t kNumInputs = 1; | 3531 const intptr_t kNumInputs = 1; |
3475 const intptr_t kNumTemps = 0; | 3532 const intptr_t kNumTemps = 0; |
3476 LocationSummary* summary = | 3533 LocationSummary* summary = |
3477 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3534 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3478 summary->set_in(0, Location::RequiresRegister()); | 3535 summary->set_in(0, Location::RequiresRegister()); |
3479 // We make use of 3-operand instructions by not requiring result register | 3536 // We make use of 3-operand instructions by not requiring result register |
(...skipping 896 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4376 compiler->GenerateCall(token_pos(), | 4433 compiler->GenerateCall(token_pos(), |
4377 &label, | 4434 &label, |
4378 PcDescriptors::kOther, | 4435 PcDescriptors::kOther, |
4379 locs()); | 4436 locs()); |
4380 __ Drop(ArgumentCount()); // Discard arguments. | 4437 __ Drop(ArgumentCount()); // Discard arguments. |
4381 } | 4438 } |
4382 | 4439 |
4383 } // namespace dart | 4440 } // namespace dart |
4384 | 4441 |
4385 #endif // defined TARGET_ARCH_ARM64 | 4442 #endif // defined TARGET_ARCH_ARM64 |
OLD | NEW |