Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(253)

Side by Side Diff: runtime/vm/intermediate_language_arm.cc

Issue 252333002: Use GPRs for mints (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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_ARM. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM.
6 #if defined(TARGET_ARCH_ARM) 6 #if defined(TARGET_ARCH_ARM)
7 7
8 #include "vm/intermediate_language.h" 8 #include "vm/intermediate_language.h"
9 9
10 #include "vm/cpu.h" 10 #include "vm/cpu.h"
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after
373 default: 373 default:
374 UNREACHABLE(); 374 UNREACHABLE();
375 return VS; 375 return VS;
376 } 376 }
377 } 377 }
378 378
379 379
380 LocationSummary* EqualityCompareInstr::MakeLocationSummary(bool opt) const { 380 LocationSummary* EqualityCompareInstr::MakeLocationSummary(bool opt) const {
381 const intptr_t kNumInputs = 2; 381 const intptr_t kNumInputs = 2;
382 if (operation_cid() == kMintCid) { 382 if (operation_cid() == kMintCid) {
383 const intptr_t kNumTemps = 3; 383 const intptr_t kNumTemps = 0;
384 LocationSummary* locs = 384 LocationSummary* locs =
385 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 385 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
386 locs->set_in(0, Location::RequiresFpuRegister()); 386 locs->set_in(0, Location::Pair(Location::RequiresRegister(),
387 locs->set_in(1, Location::RequiresFpuRegister()); 387 Location::RequiresRegister()));
388 locs->set_temp(0, Location::RequiresFpuRegister()); 388 locs->set_in(1, Location::Pair(Location::RequiresRegister(),
389 locs->set_temp(1, Location::RequiresRegister()); 389 Location::RequiresRegister()));
390 locs->set_temp(2, Location::RequiresRegister());
391 locs->set_out(0, Location::RequiresRegister()); 390 locs->set_out(0, Location::RequiresRegister());
392 return locs; 391 return locs;
393 } 392 }
394 if (operation_cid() == kDoubleCid) { 393 if (operation_cid() == kDoubleCid) {
395 const intptr_t kNumTemps = 0; 394 const intptr_t kNumTemps = 0;
396 LocationSummary* locs = 395 LocationSummary* locs =
397 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 396 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
398 locs->set_in(0, Location::RequiresFpuRegister()); 397 locs->set_in(0, Location::RequiresFpuRegister());
399 locs->set_in(1, Location::RequiresFpuRegister()); 398 locs->set_in(1, Location::RequiresFpuRegister());
400 locs->set_out(0, Location::RequiresRegister()); 399 locs->set_out(0, Location::RequiresRegister());
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
508 UNREACHABLE(); 507 UNREACHABLE();
509 return VS; 508 return VS;
510 } 509 }
511 } 510 }
512 511
513 512
514 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, 513 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler,
515 LocationSummary* locs, 514 LocationSummary* locs,
516 Token::Kind kind) { 515 Token::Kind kind) {
517 ASSERT(Token::IsEqualityOperator(kind)); 516 ASSERT(Token::IsEqualityOperator(kind));
518 const QRegister left = locs->in(0).fpu_reg(); 517 PairLocation* left_pair = locs->in(0).AsPairLocation();
519 const QRegister right = locs->in(1).fpu_reg(); 518 Register left1 = left_pair->At(0).reg();
520 const QRegister tmpq = locs->temp(0).fpu_reg(); 519 Register left2 = left_pair->At(1).reg();
521 const Register tmp_lo = locs->temp(1).reg(); 520 PairLocation* right_pair = locs->in(1).AsPairLocation();
522 const Register tmp_hi = locs->temp(2).reg(); 521 Register right1 = right_pair->At(0).reg();
522 Register right2 = right_pair->At(1).reg();
523 523
524 __ vceqqi(kWord, tmpq, left, right); 524 // Compare lower.
525 __ vmovrrd(tmp_lo, tmp_hi, EvenDRegisterOf(tmpq)); 525 __ cmp(left1, ShifterOperand(right1));
526 // tmp_lo and tmp_hi must both be 0xffffffff. 526 // Compare upper if lower is equal.
527 __ and_(tmp_lo, tmp_lo, ShifterOperand(tmp_hi)); 527 __ cmp(left2, ShifterOperand(right2), EQ);
528 528 return TokenKindToMintCondition(kind);
529 Condition true_condition = TokenKindToMintCondition(kind);
530 __ CompareImmediate(tmp_lo, 0xffffffff);
531 return true_condition;
532 } 529 }
533 530
534 531
535 static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, 532 static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler,
536 LocationSummary* locs, 533 LocationSummary* locs,
537 Token::Kind kind) { 534 Token::Kind kind) {
538 const QRegister left = locs->in(0).fpu_reg(); 535 PairLocation* left_pair = locs->in(0).AsPairLocation();
539 const QRegister right = locs->in(1).fpu_reg(); 536 Register left1 = left_pair->At(0).reg();
540 const DRegister dleft0 = EvenDRegisterOf(left); 537 Register left2 = left_pair->At(1).reg();
541 const DRegister dright0 = EvenDRegisterOf(right); 538 PairLocation* right_pair = locs->in(1).AsPairLocation();
542 const SRegister sleft0 = EvenSRegisterOf(dleft0); 539 Register right1 = right_pair->At(0).reg();
543 const SRegister sleft1 = OddSRegisterOf(dleft0); 540 Register right2 = right_pair->At(1).reg();
544 const SRegister sright0 = EvenSRegisterOf(dright0);
545 const SRegister sright1 = OddSRegisterOf(dright0);
546 541
547 const Register tmp_left = locs->temp(0).reg(); 542 Register out = locs->temp(0).reg();
548 const Register tmp_right = locs->temp(1).reg();
549 543
550 // 64-bit comparison 544 // 64-bit comparison
551 Condition hi_true_cond, hi_false_cond, lo_false_cond; 545 Condition hi_true_cond, hi_false_cond, lo_false_cond;
552 switch (kind) { 546 switch (kind) {
553 case Token::kLT: 547 case Token::kLT:
554 case Token::kLTE: 548 case Token::kLTE:
555 hi_true_cond = LT; 549 hi_true_cond = LT;
556 hi_false_cond = GT; 550 hi_false_cond = GT;
557 lo_false_cond = (kind == Token::kLT) ? CS : HI; 551 lo_false_cond = (kind == Token::kLT) ? CS : HI;
558 break; 552 break;
559 case Token::kGT: 553 case Token::kGT:
560 case Token::kGTE: 554 case Token::kGTE:
561 hi_true_cond = GT; 555 hi_true_cond = GT;
562 hi_false_cond = LT; 556 hi_false_cond = LT;
563 lo_false_cond = (kind == Token::kGT) ? LS : CC; 557 lo_false_cond = (kind == Token::kGT) ? LS : CC;
564 break; 558 break;
565 default: 559 default:
566 UNREACHABLE(); 560 UNREACHABLE();
567 hi_true_cond = hi_false_cond = lo_false_cond = VS; 561 hi_true_cond = hi_false_cond = lo_false_cond = VS;
568 } 562 }
569 563
570 Label is_true, is_false, done; 564 Label is_true, is_false, done;
571 __ vmovrs(tmp_left, sleft1); 565 // Compare upper halves first.
572 __ vmovrs(tmp_right, sright1); 566 __ cmp(left2, ShifterOperand(right2));
573 __ cmp(tmp_left, ShifterOperand(tmp_right)); 567 __ LoadImmediate(out, 0, hi_false_cond);
574 __ b(&is_false, hi_false_cond); 568 __ LoadImmediate(out, 1, hi_true_cond);
575 __ b(&is_true, hi_true_cond); 569 // If higher words aren't equal, skip comparing lower words.
570 __ b(&done, NE);
576 571
577 __ vmovrs(tmp_left, sleft0); 572 __ cmp(left1, ShifterOperand(right1));
578 __ vmovrs(tmp_right, sright0); 573 __ LoadImmediate(out, 1);
579 __ cmp(tmp_left, ShifterOperand(tmp_right)); 574 __ LoadImmediate(out, 0, lo_false_cond);
580 __ b(&is_false, lo_false_cond); 575 __ Bind(&done);
581 // Else is true.
582 __ b(&is_true);
583 576
584 __ Bind(&is_false);
585 __ LoadImmediate(tmp_left, 0);
586 __ b(&done);
587 __ Bind(&is_true);
588 __ LoadImmediate(tmp_left, 1);
589 __ Bind(&done);
590 return NegateCondition(lo_false_cond); 577 return NegateCondition(lo_false_cond);
591 } 578 }
592 579
593 580
594 static Condition TokenKindToDoubleCondition(Token::Kind kind) { 581 static Condition TokenKindToDoubleCondition(Token::Kind kind) {
595 switch (kind) { 582 switch (kind) {
596 case Token::kEQ: return EQ; 583 case Token::kEQ: return EQ;
597 case Token::kNE: return NE; 584 case Token::kNE: return NE;
598 case Token::kLT: return LT; 585 case Token::kLT: return LT;
599 case Token::kGT: return GT; 586 case Token::kGT: return GT;
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
786 __ Bind(&is_true); 773 __ Bind(&is_true);
787 __ LoadObject(result_reg, Bool::True()); 774 __ LoadObject(result_reg, Bool::True());
788 __ Bind(&done); 775 __ Bind(&done);
789 } 776 }
790 777
791 778
792 LocationSummary* RelationalOpInstr::MakeLocationSummary(bool opt) const { 779 LocationSummary* RelationalOpInstr::MakeLocationSummary(bool opt) const {
793 const intptr_t kNumInputs = 2; 780 const intptr_t kNumInputs = 2;
794 const intptr_t kNumTemps = 0; 781 const intptr_t kNumTemps = 0;
795 if (operation_cid() == kMintCid) { 782 if (operation_cid() == kMintCid) {
796 const intptr_t kNumTemps = 2; 783 const intptr_t kNumTemps = 1;
797 LocationSummary* locs = 784 LocationSummary* locs =
798 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 785 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
799 locs->set_in(0, Location::RequiresFpuRegister()); 786 locs->set_in(0, Location::Pair(Location::RequiresRegister(),
800 locs->set_in(1, Location::RequiresFpuRegister()); 787 Location::RequiresRegister()));
788 locs->set_in(1, Location::Pair(Location::RequiresRegister(),
789 Location::RequiresRegister()));
801 locs->set_temp(0, Location::RequiresRegister()); 790 locs->set_temp(0, Location::RequiresRegister());
802 locs->set_temp(1, Location::RequiresRegister());
803 locs->set_out(0, Location::RequiresRegister()); 791 locs->set_out(0, Location::RequiresRegister());
804 return locs; 792 return locs;
805 } 793 }
806 if (operation_cid() == kDoubleCid) { 794 if (operation_cid() == kDoubleCid) {
807 LocationSummary* summary = 795 LocationSummary* summary =
808 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 796 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
809 summary->set_in(0, Location::RequiresFpuRegister()); 797 summary->set_in(0, Location::RequiresFpuRegister());
810 summary->set_in(1, Location::RequiresFpuRegister()); 798 summary->set_in(1, Location::RequiresFpuRegister());
811 summary->set_out(0, Location::RequiresRegister()); 799 summary->set_out(0, Location::RequiresRegister());
812 return summary; 800 return summary;
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after
1146 (representation() == kUnboxedInt32x4) || 1134 (representation() == kUnboxedInt32x4) ||
1147 (representation() == kUnboxedFloat64x2)) { 1135 (representation() == kUnboxedFloat64x2)) {
1148 if (class_id() == kTypedDataFloat32ArrayCid) { 1136 if (class_id() == kTypedDataFloat32ArrayCid) {
1149 // Need register <= Q7 for float operations. 1137 // Need register <= Q7 for float operations.
1150 // TODO(fschneider): Add a register policy to specify a subset of 1138 // TODO(fschneider): Add a register policy to specify a subset of
1151 // registers. 1139 // registers.
1152 locs->set_out(0, Location::FpuRegisterLocation(Q7)); 1140 locs->set_out(0, Location::FpuRegisterLocation(Q7));
1153 } else { 1141 } else {
1154 locs->set_out(0, Location::RequiresFpuRegister()); 1142 locs->set_out(0, Location::RequiresFpuRegister());
1155 } 1143 }
1144 } else if (representation() == kUnboxedMint) {
1145 locs->set_out(0, Location::Pair(Location::RequiresRegister(),
1146 Location::RequiresRegister()));
1156 } else { 1147 } else {
1148 ASSERT(representation() == kTagged);
1157 locs->set_out(0, Location::RequiresRegister()); 1149 locs->set_out(0, Location::RequiresRegister());
1158 } 1150 }
1159 return locs; 1151 return locs;
1160 } 1152 }
1161 1153
1162 1154
1163 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1155 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1164 if ((representation() == kUnboxedDouble) || 1156 if ((representation() == kUnboxedDouble) ||
1165 (representation() == kUnboxedMint) ||
1166 (representation() == kUnboxedFloat32x4) || 1157 (representation() == kUnboxedFloat32x4) ||
1167 (representation() == kUnboxedInt32x4) || 1158 (representation() == kUnboxedInt32x4) ||
1168 (representation() == kUnboxedFloat64x2)) { 1159 (representation() == kUnboxedFloat64x2)) {
1169 const Register array = locs()->in(0).reg(); 1160 const Register array = locs()->in(0).reg();
1170 const Register idx = locs()->in(1).reg(); 1161 const Register idx = locs()->in(1).reg();
1171 switch (index_scale()) { 1162 switch (index_scale()) {
1172 case 1: 1163 case 1:
1173 __ add(idx, array, ShifterOperand(idx, ASR, kSmiTagSize)); 1164 __ add(idx, array, ShifterOperand(idx, ASR, kSmiTagSize));
1174 break; 1165 break;
1175 case 4: 1166 case 4:
(...skipping 11 matching lines...) Expand all
1187 } 1178 }
1188 if (!IsExternal()) { 1179 if (!IsExternal()) {
1189 ASSERT(this->array()->definition()->representation() == kTagged); 1180 ASSERT(this->array()->definition()->representation() == kTagged);
1190 __ AddImmediate(idx, 1181 __ AddImmediate(idx,
1191 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag); 1182 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag);
1192 } 1183 }
1193 Address element_address(idx); 1184 Address element_address(idx);
1194 const QRegister result = locs()->out(0).fpu_reg(); 1185 const QRegister result = locs()->out(0).fpu_reg();
1195 const DRegister dresult0 = EvenDRegisterOf(result); 1186 const DRegister dresult0 = EvenDRegisterOf(result);
1196 switch (class_id()) { 1187 switch (class_id()) {
1197 case kTypedDataInt32ArrayCid:
1198 __ veorq(result, result, result);
1199 __ ldr(TMP, element_address);
1200 // Re-use the index register so we don't have to require a low-numbered
1201 // Q register.
1202 // Sign-extend into idx.
1203 __ Asr(idx, TMP, 31);
1204 __ vmovdrr(dresult0, TMP, idx);
1205 break;
1206 case kTypedDataUint32ArrayCid:
1207 __ veorq(result, result, result);
1208 __ ldr(TMP, element_address);
1209 // Re-use the index register so we don't have to require a low-numbered
1210 // Q register.
1211 __ LoadImmediate(idx, 0);
1212 __ vmovdrr(dresult0, TMP, idx);
1213 break;
1214 case kTypedDataFloat32ArrayCid: 1188 case kTypedDataFloat32ArrayCid:
1215 // Load single precision float. 1189 // Load single precision float.
1216 // vldrs does not support indexed addressing. 1190 // vldrs does not support indexed addressing.
1217 __ vldrs(EvenSRegisterOf(dresult0), element_address); 1191 __ vldrs(EvenSRegisterOf(dresult0), element_address);
1218 break; 1192 break;
1219 case kTypedDataFloat64ArrayCid: 1193 case kTypedDataFloat64ArrayCid:
1220 // vldrd does not support indexed addressing. 1194 // vldrd does not support indexed addressing.
1221 __ vldrd(dresult0, element_address); 1195 __ vldrd(dresult0, element_address);
1222 break; 1196 break;
1223 case kTypedDataFloat64x2ArrayCid: 1197 case kTypedDataFloat64x2ArrayCid:
1224 case kTypedDataInt32x4ArrayCid: 1198 case kTypedDataInt32x4ArrayCid:
1225 case kTypedDataFloat32x4ArrayCid: 1199 case kTypedDataFloat32x4ArrayCid:
1226 __ vldmd(IA, idx, dresult0, 2); 1200 __ vldmd(IA, idx, dresult0, 2);
1227 break; 1201 break;
1202 default:
1203 UNREACHABLE();
1228 } 1204 }
1229 return; 1205 return;
1230 } 1206 }
1231 1207
1232 const Register array = locs()->in(0).reg(); 1208 const Register array = locs()->in(0).reg();
1233 Location index = locs()->in(1); 1209 Location index = locs()->in(1);
1234 ASSERT(index.IsRegister()); // TODO(regis): Revisit. 1210 ASSERT(index.IsRegister()); // TODO(regis): Revisit.
1235 Address element_address(kNoRegister, 0); 1211 Address element_address(kNoRegister, 0);
1236 // Note that index is expected smi-tagged, (i.e, times 2) for all arrays 1212 // Note that index is expected smi-tagged, (i.e, times 2) for all arrays
1237 // with index scale factor > 1. E.g., for Uint8Array and OneByteString the 1213 // with index scale factor > 1. E.g., for Uint8Array and OneByteString the
(...skipping 22 matching lines...) Expand all
1260 case 4: { 1236 case 4: {
1261 __ add(index.reg(), array, ShifterOperand(index.reg(), LSL, 1)); 1237 __ add(index.reg(), array, ShifterOperand(index.reg(), LSL, 1));
1262 element_address = Address(index.reg(), offset); 1238 element_address = Address(index.reg(), offset);
1263 break; 1239 break;
1264 } 1240 }
1265 // Cases 8 and 16 are only for unboxed values and are handled above. 1241 // Cases 8 and 16 are only for unboxed values and are handled above.
1266 default: 1242 default:
1267 UNREACHABLE(); 1243 UNREACHABLE();
1268 } 1244 }
1269 1245
1270 const Register result = locs()->out(0).reg(); 1246 if (representation() == kUnboxedMint) {
1247 ASSERT(locs()->out(0).IsPairLocation());
1248 PairLocation* result_pair = locs()->out(0).AsPairLocation();
1249 Register result1 = result_pair->At(0).reg();
1250 Register result2 = result_pair->At(1).reg();
1251 switch (class_id()) {
1252 case kTypedDataInt32ArrayCid:
1253 // Load low word.
1254 __ ldr(result1, element_address);
1255 // Sign extend into high word.
1256 __ SignFill(result2, result1);
1257 break;
1258 case kTypedDataUint32ArrayCid:
1259 // Load low word.
1260 __ ldr(result1, element_address);
1261 // Zero high word.
1262 __ eor(result2, result2, ShifterOperand(result2));
1263 break;
1264 default:
1265 UNREACHABLE();
1266 break;
1267 }
1268 return;
1269 }
1270
1271 ASSERT(representation() == kTagged);
1272
1273 Register result = locs()->out(0).reg();
1271 switch (class_id()) { 1274 switch (class_id()) {
1272 case kTypedDataInt8ArrayCid: 1275 case kTypedDataInt8ArrayCid:
1273 ASSERT(index_scale() == 1); 1276 ASSERT(index_scale() == 1);
1274 __ ldrsb(result, element_address); 1277 __ ldrsb(result, element_address);
1275 __ SmiTag(result); 1278 __ SmiTag(result);
1276 break; 1279 break;
1277 case kTypedDataUint8ArrayCid: 1280 case kTypedDataUint8ArrayCid:
1278 case kTypedDataUint8ClampedArrayCid: 1281 case kTypedDataUint8ClampedArrayCid:
1279 case kExternalTypedDataUint8ArrayCid: 1282 case kExternalTypedDataUint8ArrayCid:
1280 case kExternalTypedDataUint8ClampedArrayCid: 1283 case kExternalTypedDataUint8ClampedArrayCid:
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
1377 case kTypedDataInt8ArrayCid: 1380 case kTypedDataInt8ArrayCid:
1378 case kTypedDataUint8ArrayCid: 1381 case kTypedDataUint8ArrayCid:
1379 case kTypedDataUint8ClampedArrayCid: 1382 case kTypedDataUint8ClampedArrayCid:
1380 case kOneByteStringCid: 1383 case kOneByteStringCid:
1381 case kTypedDataInt16ArrayCid: 1384 case kTypedDataInt16ArrayCid:
1382 case kTypedDataUint16ArrayCid: 1385 case kTypedDataUint16ArrayCid:
1383 locs->set_in(2, Location::WritableRegister()); 1386 locs->set_in(2, Location::WritableRegister());
1384 break; 1387 break;
1385 case kTypedDataInt32ArrayCid: 1388 case kTypedDataInt32ArrayCid:
1386 case kTypedDataUint32ArrayCid: 1389 case kTypedDataUint32ArrayCid:
1387 // Mints are stored in Q registers. For smis, use a writable register 1390 // For smis, use a writable register because the value must be untagged
1388 // because the value must be untagged before storing. 1391 // before storing. Mints are stored in register pairs.
1389 locs->set_in(2, value()->IsSmiValue() 1392 if (value()->IsSmiValue()) {
1390 ? Location::WritableRegister() 1393 locs->set_in(2, Location::WritableRegister());
1391 : Location::FpuRegisterLocation(Q7)); 1394 } else {
1395 // We only move the lower 32-bits so we don't care where the high bits
1396 // are located.
1397 locs->set_in(2, Location::Pair(Location::RequiresRegister(),
1398 Location::Any()));
1399 }
1392 break; 1400 break;
1393 case kTypedDataFloat32ArrayCid: 1401 case kTypedDataFloat32ArrayCid:
1394 // Need low register (<= Q7). 1402 // Need low register (<= Q7).
1395 locs->set_in(2, Location::FpuRegisterLocation(Q7)); 1403 locs->set_in(2, Location::FpuRegisterLocation(Q7));
1396 break; 1404 break;
1397 case kTypedDataFloat64ArrayCid: // TODO(srdjan): Support Float64 constants. 1405 case kTypedDataFloat64ArrayCid: // TODO(srdjan): Support Float64 constants.
1398 case kTypedDataInt32x4ArrayCid: 1406 case kTypedDataInt32x4ArrayCid:
1399 case kTypedDataFloat32x4ArrayCid: 1407 case kTypedDataFloat32x4ArrayCid:
1400 case kTypedDataFloat64x2ArrayCid: 1408 case kTypedDataFloat64x2ArrayCid:
1401 locs->set_in(2, Location::RequiresFpuRegister()); 1409 locs->set_in(2, Location::RequiresFpuRegister());
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
1566 } 1574 }
1567 case kTypedDataInt32ArrayCid: 1575 case kTypedDataInt32ArrayCid:
1568 case kTypedDataUint32ArrayCid: { 1576 case kTypedDataUint32ArrayCid: {
1569 if (value()->IsSmiValue()) { 1577 if (value()->IsSmiValue()) {
1570 ASSERT(RequiredInputRepresentation(2) == kTagged); 1578 ASSERT(RequiredInputRepresentation(2) == kTagged);
1571 const Register value = locs()->in(2).reg(); 1579 const Register value = locs()->in(2).reg();
1572 __ SmiUntag(value); 1580 __ SmiUntag(value);
1573 __ str(value, element_address); 1581 __ str(value, element_address);
1574 } else { 1582 } else {
1575 ASSERT(RequiredInputRepresentation(2) == kUnboxedMint); 1583 ASSERT(RequiredInputRepresentation(2) == kUnboxedMint);
1576 const QRegister value = locs()->in(2).fpu_reg(); 1584 PairLocation* value_pair = locs()->in(2).AsPairLocation();
1577 ASSERT(value == Q7); 1585 Register value1 = value_pair->At(0).reg();
1578 __ vmovrs(TMP, EvenSRegisterOf(EvenDRegisterOf(value))); 1586 __ str(value1, element_address);
1579 __ str(TMP, element_address);
1580 } 1587 }
1581 break; 1588 break;
1582 } 1589 }
1583 default: 1590 default:
1584 UNREACHABLE(); 1591 UNREACHABLE();
1585 } 1592 }
1586 } 1593 }
1587 1594
1588 1595
1589 LocationSummary* GuardFieldInstr::MakeLocationSummary(bool opt) const { 1596 LocationSummary* GuardFieldInstr::MakeLocationSummary(bool opt) const {
(...skipping 4129 matching lines...) Expand 10 before | Expand all | Expand 10 after
5719 const Register length = length_loc.reg(); 5726 const Register length = length_loc.reg();
5720 const Register index = index_loc.reg(); 5727 const Register index = index_loc.reg();
5721 __ cmp(index, ShifterOperand(length)); 5728 __ cmp(index, ShifterOperand(length));
5722 __ b(deopt, CS); 5729 __ b(deopt, CS);
5723 } 5730 }
5724 } 5731 }
5725 5732
5726 5733
5727 static void EmitJavascriptIntOverflowCheck(FlowGraphCompiler* compiler, 5734 static void EmitJavascriptIntOverflowCheck(FlowGraphCompiler* compiler,
5728 Label* overflow, 5735 Label* overflow,
5729 QRegister result, 5736 Register result_lo,
5730 Register tmp_hi, Register tmp_lo) { 5737 Register result_hi) {
5731 __ vmovrrd(tmp_lo, tmp_hi, EvenDRegisterOf(result));
5732 // Compare upper half. 5738 // Compare upper half.
5733 Label check_lower; 5739 Label check_lower;
5734 __ CompareImmediate(tmp_hi, 0x00200000); 5740 __ CompareImmediate(result_hi, 0x00200000);
5735 __ b(overflow, GT); 5741 __ b(overflow, GT);
5736 __ b(&check_lower, NE); 5742 __ b(&check_lower, NE);
5737 5743
5738 __ CompareImmediate(tmp_lo, 0); 5744 __ CompareImmediate(result_lo, 0);
5739 __ b(overflow, HI); 5745 __ b(overflow, HI);
5740 5746
5741 __ Bind(&check_lower); 5747 __ Bind(&check_lower);
5742 __ CompareImmediate(tmp_hi, -0x00200000); 5748 __ CompareImmediate(result_hi, -0x00200000);
5743 __ b(overflow, LT); 5749 __ b(overflow, LT);
5744 // Anything in the lower part would make the number bigger than the lower 5750 // Anything in the lower part would make the number bigger than the lower
5745 // bound, so we are done. 5751 // bound, so we are done.
5746 } 5752 }
5747 5753
5748 5754
5749 LocationSummary* UnboxIntegerInstr::MakeLocationSummary(bool opt) const { 5755 LocationSummary* UnboxIntegerInstr::MakeLocationSummary(bool opt) const {
5750 const intptr_t kNumInputs = 1; 5756 const intptr_t kNumInputs = 1;
5751 const intptr_t value_cid = value()->Type()->ToCid(); 5757 const intptr_t kNumTemps = 1;
5752 const bool needs_writable_input = (value_cid != kMintCid);
5753 const bool needs_temp = (value_cid != kMintCid);
5754 const intptr_t kNumTemps = needs_temp ? 1 : 0;
5755 LocationSummary* summary = 5758 LocationSummary* summary =
5756 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 5759 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
5757 summary->set_in(0, needs_writable_input 5760 summary->set_in(0, Location::RequiresRegister());
5758 ? Location::WritableRegister() 5761 summary->set_temp(0, Location::RequiresRegister());
5759 : Location::RequiresRegister()); 5762 summary->set_out(0, Location::Pair(Location::RequiresRegister(),
5760 if (needs_temp) { 5763 Location::RequiresRegister()));
5761 summary->set_temp(0, Location::RequiresRegister());
5762 }
5763 summary->set_out(0, Location::RequiresFpuRegister());
5764 return summary; 5764 return summary;
5765 } 5765 }
5766 5766
5767 5767
5768 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5768 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5769 const intptr_t value_cid = value()->Type()->ToCid(); 5769 const intptr_t value_cid = value()->Type()->ToCid();
5770 const Register value = locs()->in(0).reg(); 5770 const Register value = locs()->in(0).reg();
5771 const QRegister result = locs()->out(0).fpu_reg(); 5771 PairLocation* result_pair = locs()->out(0).AsPairLocation();
5772 Register result_lo = result_pair->At(0).reg();
5773 Register result_hi = result_pair->At(1).reg();
5774 ASSERT(value != result_lo);
5775 ASSERT(value != result_hi);
5772 5776
5773 __ Comment("UnboxIntegerInstr"); 5777 __ Comment("UnboxIntegerInstr");
5774 __ veorq(result, result, result);
5775 if (value_cid == kMintCid) { 5778 if (value_cid == kMintCid) {
5776 __ LoadDFromOffset(EvenDRegisterOf(result), value, 5779 // Load low word.
5777 Mint::value_offset() - kHeapObjectTag); 5780 __ LoadFromOffset(kWord,
5781 result_lo,
5782 value,
5783 Mint::value_offset() - kHeapObjectTag);
5784 // Load high word.
5785 __ LoadFromOffset(kWord,
5786 result_hi,
5787 value,
5788 Mint::value_offset() - kHeapObjectTag + kWordSize);
5778 } else if (value_cid == kSmiCid) { 5789 } else if (value_cid == kSmiCid) {
5779 const Register temp = locs()->temp(0).reg(); 5790 // Load Smi into result_lo.
5780 __ SmiUntag(value); 5791 __ mov(result_lo, ShifterOperand(value));
5781 // Sign extend value into temp. 5792 // Untag.
5782 __ Asr(temp, value, 31); 5793 __ SmiUntag(result_lo);
5783 __ vmovdrr(EvenDRegisterOf(result), value, temp); 5794 __ SignFill(result_hi, result_lo);
5784 } else { 5795 } else {
5785 const Register temp = locs()->temp(0).reg(); 5796 const Register temp = locs()->temp(0).reg();
5786 Label* deopt = compiler->AddDeoptStub(deopt_id_, 5797 Label* deopt = compiler->AddDeoptStub(deopt_id_,
5787 ICData::kDeoptUnboxInteger); 5798 ICData::kDeoptUnboxInteger);
5788 Label is_smi, done; 5799 Label is_smi, done;
5789 __ tst(value, ShifterOperand(kSmiTagMask)); 5800 __ tst(value, ShifterOperand(kSmiTagMask));
5790 __ b(&is_smi, EQ); 5801 __ b(&is_smi, EQ);
5791 __ CompareClassId(value, kMintCid, temp); 5802 __ CompareClassId(value, kMintCid, temp);
5792 __ b(deopt, NE); 5803 __ b(deopt, NE);
5793 5804
5794 // It's a Mint. 5805 // It's a Mint.
5795 __ LoadDFromOffset(EvenDRegisterOf(result), value, 5806 // Load low word.
5796 Mint::value_offset() - kHeapObjectTag); 5807 __ LoadFromOffset(kWord,
5808 result_lo,
5809 value,
5810 Mint::value_offset() - kHeapObjectTag);
5811 // Load high word.
5812 __ LoadFromOffset(kWord,
5813 result_hi,
5814 value,
5815 Mint::value_offset() - kHeapObjectTag + kWordSize);
5797 __ b(&done); 5816 __ b(&done);
5798 5817
5799 // It's a Smi. 5818 // It's a Smi.
5800 __ Bind(&is_smi); 5819 __ Bind(&is_smi);
5801 __ SmiUntag(value); 5820 // Load Smi into result_lo.
5802 // Sign extend into temp. 5821 __ mov(result_lo, ShifterOperand(value));
5803 __ Asr(temp, value, 31); 5822 // Untag.
5804 __ vmovdrr(EvenDRegisterOf(result), value, temp); 5823 __ SmiUntag(result_lo);
5824 // Sign extend result_lo into result_hi.
5825 __ SignFill(result_hi, result_lo);
5805 __ Bind(&done); 5826 __ Bind(&done);
5806 } 5827 }
5807 } 5828 }
5808 5829
5809 5830
5810 LocationSummary* BoxIntegerInstr::MakeLocationSummary(bool opt) const { 5831 LocationSummary* BoxIntegerInstr::MakeLocationSummary(bool opt) const {
5811 const intptr_t kNumInputs = 1; 5832 const intptr_t kNumInputs = 1;
5812 const intptr_t kNumTemps = 2; 5833 const intptr_t kNumTemps = 1;
5813 LocationSummary* summary = 5834 LocationSummary* summary =
5814 new LocationSummary(kNumInputs, 5835 new LocationSummary(kNumInputs,
5815 kNumTemps, 5836 kNumTemps,
5816 LocationSummary::kCallOnSlowPath); 5837 LocationSummary::kCallOnSlowPath);
5817 summary->set_in(0, Location::RequiresFpuRegister()); 5838 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
5839 Location::RequiresRegister()));
5818 summary->set_temp(0, Location::RequiresRegister()); 5840 summary->set_temp(0, Location::RequiresRegister());
5819 summary->set_temp(1, Location::RequiresRegister());
5820 summary->set_out(0, Location::RequiresRegister()); 5841 summary->set_out(0, Location::RequiresRegister());
5821 return summary; 5842 return summary;
5822 } 5843 }
5823 5844
5824 5845
5825 class BoxIntegerSlowPath : public SlowPathCode { 5846 class BoxIntegerSlowPath : public SlowPathCode {
5826 public: 5847 public:
5827 explicit BoxIntegerSlowPath(BoxIntegerInstr* instruction) 5848 explicit BoxIntegerSlowPath(BoxIntegerInstr* instruction)
5828 : instruction_(instruction) { } 5849 : instruction_(instruction) { }
5829 5850
(...skipping 21 matching lines...) Expand all
5851 } 5872 }
5852 5873
5853 private: 5874 private:
5854 BoxIntegerInstr* instruction_; 5875 BoxIntegerInstr* instruction_;
5855 }; 5876 };
5856 5877
5857 5878
5858 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5879 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5859 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this); 5880 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this);
5860 compiler->AddSlowPathCode(slow_path); 5881 compiler->AddSlowPathCode(slow_path);
5861 5882 PairLocation* value_pair = locs()->in(0).AsPairLocation();
5862 const Register out_reg = locs()->out(0).reg(); 5883 Register value_lo = value_pair->At(0).reg();
5863 const QRegister value = locs()->in(0).fpu_reg(); 5884 Register value_hi = value_pair->At(1).reg();
5864 const DRegister dvalue0 = EvenDRegisterOf(value); 5885 Register tmp = locs()->temp(0).reg();
5865 const Register lo = locs()->temp(0).reg(); 5886 Register out_reg = locs()->out(0).reg();
5866 const Register hi = locs()->temp(1).reg();
5867 5887
5868 // Unboxed operations produce smis or mint-sized values. 5888 // Unboxed operations produce smis or mint-sized values.
5869 // Check if value fits into a smi. 5889 // Check if value fits into a smi.
5870 __ Comment("BoxIntegerInstr"); 5890 __ Comment("BoxIntegerInstr");
5871 Label not_smi, done, maybe_pos_smi, maybe_neg_smi, is_smi; 5891 Label not_smi, done, maybe_pos_smi, maybe_neg_smi, is_smi;
5872 __ vmovrrd(lo, hi, dvalue0); 5892 // Check high word.
5873 __ CompareImmediate(hi, 0); 5893 __ CompareImmediate(value_hi, 0);
5874 __ b(&maybe_pos_smi, EQ); 5894 __ b(&maybe_pos_smi, EQ);
5875 5895
5876 __ CompareImmediate(hi, -1); 5896 __ CompareImmediate(value_hi, -1);
5877 __ b(&maybe_neg_smi, EQ); 5897 __ b(&maybe_neg_smi, EQ);
5878 __ b(&not_smi); 5898 __ b(&not_smi);
5879 5899
5880 __ Bind(&maybe_pos_smi); 5900 __ Bind(&maybe_pos_smi);
5881 __ CompareImmediate(lo, kSmiMax); 5901 __ CompareImmediate(value_lo, kSmiMax);
5882 __ b(&is_smi, LS); // unsigned lower or same. 5902 __ b(&is_smi, LS); // unsigned lower or same.
5883 __ b(&not_smi); 5903 __ b(&not_smi);
5884 5904
5885 __ Bind(&maybe_neg_smi); 5905 __ Bind(&maybe_neg_smi);
5886 __ CompareImmediate(lo, 0); 5906 __ CompareImmediate(value_lo, 0);
5887 __ b(&not_smi, GE); 5907 __ b(&not_smi, GE);
5888 __ CompareImmediate(lo, kSmiMin); 5908 __ CompareImmediate(value_lo, kSmiMin);
5889 __ b(&not_smi, LT); 5909 __ b(&not_smi, LT);
5890 5910
5891 // lo is a Smi. Tag it and return. 5911 // lo is a Smi. Tag it and return.
5892 __ Bind(&is_smi); 5912 __ Bind(&is_smi);
5893 __ SmiTag(lo); 5913 __ mov(out_reg, ShifterOperand(value_lo));
5894 __ mov(out_reg, ShifterOperand(lo)); 5914 __ SmiTag(out_reg);
5895 __ b(&done); 5915 __ b(&done);
5896 5916
5897 // Not a smi. Box it. 5917 // Not a smi. Box it.
5898 __ Bind(&not_smi); 5918 __ Bind(&not_smi);
5899 __ TryAllocate( 5919 __ TryAllocate(
5900 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()), 5920 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()),
5901 slow_path->entry_label(), 5921 slow_path->entry_label(),
5902 out_reg, 5922 out_reg,
5903 lo); 5923 tmp);
5904 __ Bind(slow_path->exit_label()); 5924 __ Bind(slow_path->exit_label());
5905 __ StoreDToOffset(dvalue0, out_reg, Mint::value_offset() - kHeapObjectTag); 5925 __ StoreToOffset(kWord,
5926 value_lo,
5927 out_reg,
5928 Mint::value_offset() - kHeapObjectTag);
5929 __ StoreToOffset(kWord,
5930 value_hi,
5931 out_reg,
5932 Mint::value_offset() - kHeapObjectTag + kWordSize);
5906 __ Bind(&done); 5933 __ Bind(&done);
5907 } 5934 }
5908 5935
5909 5936
5910 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(bool opt) const { 5937 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(bool opt) const {
5911 const intptr_t kNumInputs = 2; 5938 const intptr_t kNumInputs = 2;
5912 const intptr_t kNumTemps = 5939 const intptr_t kNumTemps = 0;
5913 FLAG_throw_on_javascript_int_overflow ? 2 : 0;
5914 LocationSummary* summary = 5940 LocationSummary* summary =
5915 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 5941 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
5916 summary->set_in(0, Location::RequiresFpuRegister()); 5942 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
5917 summary->set_in(1, Location::RequiresFpuRegister()); 5943 Location::RequiresRegister()));
5918 if (FLAG_throw_on_javascript_int_overflow) { 5944 summary->set_in(1, Location::Pair(Location::RequiresRegister(),
5919 summary->set_temp(0, Location::RequiresRegister()); 5945 Location::RequiresRegister()));
5920 summary->set_temp(1, Location::RequiresRegister()); 5946 summary->set_out(0, Location::Pair(Location::RequiresRegister(),
5921 } 5947 Location::RequiresRegister()));
5922 if ((op_kind() == Token::kADD) || (op_kind() == Token::kSUB)) {
5923 // Need another temp for checking for overflow.
5924 summary->AddTemp(Location::RequiresFpuRegister());
5925 summary->AddTemp(Location::FpuRegisterLocation(Q7));
5926 }
5927 summary->set_out(0, Location::RequiresFpuRegister());
5928 return summary; 5948 return summary;
5929 } 5949 }
5930 5950
5931 5951
5932 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5952 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5933 const QRegister left = locs()->in(0).fpu_reg(); 5953 PairLocation* left_pair = locs()->in(0).AsPairLocation();
5934 const QRegister right = locs()->in(1).fpu_reg(); 5954 Register left_lo = left_pair->At(0).reg();
5935 const QRegister out = locs()->out(0).fpu_reg(); 5955 Register left_hi = left_pair->At(1).reg();
5956 PairLocation* right_pair = locs()->in(1).AsPairLocation();
5957 Register right_lo = right_pair->At(0).reg();
5958 Register right_hi = right_pair->At(1).reg();
5959 PairLocation* out_pair = locs()->out(0).AsPairLocation();
5960 Register out_lo = out_pair->At(0).reg();
5961 Register out_hi = out_pair->At(1).reg();
5936 5962
5937 Label* deopt = NULL; 5963 Label* deopt = NULL;
5938 if (FLAG_throw_on_javascript_int_overflow) { 5964 if (FLAG_throw_on_javascript_int_overflow) {
5939 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); 5965 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp);
5940 } 5966 }
5941 switch (op_kind()) { 5967 switch (op_kind()) {
5942 case Token::kBIT_AND: __ vandq(out, left, right); break; 5968 case Token::kBIT_AND: {
5943 case Token::kBIT_OR: __ vorrq(out, left, right); break; 5969 __ and_(out_lo, left_lo, ShifterOperand(right_lo));
5944 case Token::kBIT_XOR: __ veorq(out, left, right); break; 5970 __ and_(out_hi, left_hi, ShifterOperand(right_hi));
5971 }
5972 break;
5973 case Token::kBIT_OR: {
5974 __ orr(out_lo, left_lo, ShifterOperand(right_lo));
5975 __ orr(out_hi, left_hi, ShifterOperand(right_hi));
5976 }
5977 break;
5978 case Token::kBIT_XOR: {
5979 __ eor(out_lo, left_lo, ShifterOperand(right_lo));
5980 __ eor(out_hi, left_hi, ShifterOperand(right_hi));
5981 }
5982 break;
5945 case Token::kADD: 5983 case Token::kADD:
5946 case Token::kSUB: { 5984 case Token::kSUB: {
5947 const intptr_t tmpidx = FLAG_throw_on_javascript_int_overflow ? 2 : 0;
5948 const QRegister tmp = locs()->temp(tmpidx).fpu_reg();
5949 const QRegister ro = locs()->temp(tmpidx + 1).fpu_reg();
5950 ASSERT(ro == Q7);
5951 if (!FLAG_throw_on_javascript_int_overflow) { 5985 if (!FLAG_throw_on_javascript_int_overflow) {
5952 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); 5986 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp);
5953 } 5987 }
5954 if (op_kind() == Token::kADD) { 5988 if (op_kind() == Token::kADD) {
5955 __ vaddqi(kWordPair, out, left, right); 5989 __ adds(out_lo, left_lo, ShifterOperand(right_lo));
5990 __ adcs(out_hi, left_hi, ShifterOperand(right_hi));
5956 } else { 5991 } else {
5957 ASSERT(op_kind() == Token::kSUB); 5992 ASSERT(op_kind() == Token::kSUB);
5958 __ vsubqi(kWordPair, out, left, right); 5993 __ subs(out_lo, left_lo, ShifterOperand(right_lo));
5994 __ sbcs(out_hi, left_hi, ShifterOperand(right_hi));
5959 } 5995 }
5960 __ veorq(ro, out, left); 5996 // Deopt on overflow.
5961 __ veorq(tmp, left, right); 5997 __ b(deopt, VS);
5962 __ vandq(ro, tmp, ro);
5963 __ vmovrs(TMP, OddSRegisterOf(EvenDRegisterOf(ro)));
5964 // If TMP < 0, there was overflow.
5965 __ cmp(TMP, ShifterOperand(0));
5966 __ b(deopt, LT);
5967 break; 5998 break;
5968 } 5999 }
5969 default: UNREACHABLE(); break; 6000 default:
6001 UNREACHABLE();
6002 break;
5970 } 6003 }
5971 if (FLAG_throw_on_javascript_int_overflow) { 6004 if (FLAG_throw_on_javascript_int_overflow) {
5972 const Register tmp1 = locs()->temp(0).reg(); 6005 EmitJavascriptIntOverflowCheck(compiler, deopt, out_lo, out_hi);
5973 const Register tmp2 = locs()->temp(1).reg();
5974 EmitJavascriptIntOverflowCheck(compiler, deopt, out, tmp1, tmp2);
5975 } 6006 }
5976 } 6007 }
5977 6008
5978 6009
5979 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(bool opt) const { 6010 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(bool opt) const {
5980 const intptr_t kNumInputs = 2; 6011 const intptr_t kNumInputs = 2;
5981 const intptr_t kNumTemps = 6012 const intptr_t kNumTemps = 1;
5982 FLAG_throw_on_javascript_int_overflow ? 2 : 1;
5983 LocationSummary* summary = 6013 LocationSummary* summary =
5984 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 6014 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
5985 summary->set_in(0, Location::RequiresFpuRegister()); 6015 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
6016 Location::RequiresRegister()));
5986 summary->set_in(1, Location::WritableRegister()); 6017 summary->set_in(1, Location::WritableRegister());
5987 summary->set_temp(0, Location::FpuRegisterLocation(Q7)); 6018 summary->set_temp(0, Location::RequiresRegister());
5988 if (FLAG_throw_on_javascript_int_overflow) { 6019 summary->set_out(0, Location::Pair(Location::RequiresRegister(),
5989 summary->set_temp(1, Location::RequiresRegister()); 6020 Location::RequiresRegister()));
5990 }
5991 summary->set_out(0, Location::RequiresFpuRegister());
5992 return summary; 6021 return summary;
5993 } 6022 }
5994 6023
5995 6024
5996 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 6025 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5997 const QRegister value = locs()->in(0).fpu_reg(); 6026 PairLocation* left_pair = locs()->in(0).AsPairLocation();
5998 const Register shift = locs()->in(1).reg(); 6027 Register left_lo = left_pair->At(0).reg();
5999 const QRegister temp = locs()->temp(0).fpu_reg(); 6028 Register left_hi = left_pair->At(1).reg();
6000 ASSERT(temp == Q7); 6029 Register shift = locs()->in(1).reg();
6001 const QRegister out = locs()->out(0).fpu_reg(); 6030 PairLocation* out_pair = locs()->out(0).AsPairLocation();
6002 const DRegister dtemp0 = EvenDRegisterOf(temp); 6031 Register out_lo = out_pair->At(0).reg();
6003 const SRegister stemp0 = EvenSRegisterOf(dtemp0); 6032 Register out_hi = out_pair->At(1).reg();
6004 const SRegister stemp1 = OddSRegisterOf(dtemp0); 6033 Register temp = locs()->temp(0).reg();
6005 6034
6006 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp); 6035 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp);
6007 Label done; 6036 Label done;
6008 6037
6038 // Early out if shift is 0.
6009 __ CompareImmediate(shift, 0); 6039 __ CompareImmediate(shift, 0);
6010 __ vmovq(out, value); 6040 __ mov(out_lo, ShifterOperand(left_lo));
6041 __ mov(out_hi, ShifterOperand(left_hi));
6011 __ b(&done, EQ); 6042 __ b(&done, EQ);
6043
6044 // Untag shift count.
6012 __ SmiUntag(shift); 6045 __ SmiUntag(shift);
6013 6046
6014 // vshlq takes the shift value from low byte. Deopt if shift is 6047 // Deopt if shift is negative.
6015 // outside of [0, 63]. 6048 __ CompareImmediate(shift, 1);
6049 __ b(deopt, LT);
6050
6051 // Deopt if shift is larger than 63.
6016 __ CompareImmediate(shift, 63); 6052 __ CompareImmediate(shift, 63);
6017 __ b(deopt, GT); 6053 __ b(deopt, GT);
6018 __ CompareImmediate(shift, 0);
6019 __ b(deopt, LT);
6020 6054
6021 __ veorq(temp, temp, temp); // Zero out temp.
6022 switch (op_kind()) { 6055 switch (op_kind()) {
6023 case Token::kSHR: { 6056 case Token::kSHR: {
6024 __ rsb(shift, shift, ShifterOperand(0)); // Negate shift. 6057 __ cmp(shift, ShifterOperand(32));
6025 __ vmovsr(stemp0, shift); // Move the shift into the low S register. 6058
6026 __ vshlqi(kWordPair, out, value, temp); 6059 __ mov(out_lo, ShifterOperand(out_hi), HI);
6060 __ Asr(out_hi, out_hi, 31, HI);
6061 __ sub(shift, shift, ShifterOperand(32), HI);
6062
6063 __ rsb(temp, shift, ShifterOperand(32));
6064 __ mov(temp, ShifterOperand(out_hi, LSL, temp));
6065 __ orr(out_lo, temp, ShifterOperand(out_lo, LSR, shift));
6066 __ Asr(out_hi, out_hi, shift);
6027 break; 6067 break;
6028 } 6068 }
6029 case Token::kSHL: { 6069 case Token::kSHL: {
6030 __ vmovsr(stemp0, shift); // Move the shift into the low S register. 6070 __ rsbs(temp, shift, ShifterOperand(32));
6031 __ vshlqu(kWordPair, out, value, temp); 6071 __ sub(temp, shift, ShifterOperand(32), MI);
6072 __ mov(out_hi, ShifterOperand(out_lo, LSL, temp), MI);
6073 __ mov(out_hi, ShifterOperand(out_hi, LSL, shift), PL);
6074 __ orr(out_hi, out_hi, ShifterOperand(out_lo, LSR, temp), PL);
6075 __ mov(out_lo, ShifterOperand(out_lo, LSL, shift));
6032 6076
6033 // check for overflow by shifting back and comparing. 6077 // Check for overflow.
6034 __ rsb(shift, shift, ShifterOperand(0)); 6078
6035 __ vmovsr(stemp0, shift); 6079 // Copy high word from output.
6036 __ vshlqi(kWordPair, temp, out, temp); 6080 __ mov(temp, ShifterOperand(out_hi));
6037 __ vceqqi(kWord, temp, temp, value); 6081 // Shift copy right.
6038 // Low 64 bits of temp should be all 1's, otherwise temp != value and 6082 __ Asr(temp, temp, shift);
6039 // we deopt. 6083 // Compare with high word from input.
6040 __ vmovrs(shift, stemp0); 6084 __ cmp(temp, ShifterOperand(left_hi));
6041 __ CompareImmediate(shift, -1); 6085 // Overflow if they aren't equal.
6042 __ b(deopt, NE);
6043 __ vmovrs(shift, stemp1);
6044 __ CompareImmediate(shift, -1);
6045 __ b(deopt, NE); 6086 __ b(deopt, NE);
6046 break; 6087 break;
6047 } 6088 }
6048 default: 6089 default:
6049 UNREACHABLE(); 6090 UNREACHABLE();
6050 break; 6091 break;
6051 } 6092 }
6052 6093
6053 __ Bind(&done); 6094 __ Bind(&done);
6054 if (FLAG_throw_on_javascript_int_overflow) { 6095 if (FLAG_throw_on_javascript_int_overflow) {
6055 const Register tmp1 = locs()->in(1).reg(); 6096 EmitJavascriptIntOverflowCheck(compiler, deopt, out_lo, out_hi);
6056 const Register tmp2 = locs()->temp(1).reg();
6057 EmitJavascriptIntOverflowCheck(compiler, deopt, out, tmp1, tmp2);
6058 } 6097 }
6059 } 6098 }
6060 6099
6061 6100
6062 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(bool opt) const { 6101 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(bool opt) const {
6063 const intptr_t kNumInputs = 1; 6102 const intptr_t kNumInputs = 1;
6064 const intptr_t kNumTemps = 6103 const intptr_t kNumTemps = 0;
6065 FLAG_throw_on_javascript_int_overflow ? 2 : 0;
6066 LocationSummary* summary = 6104 LocationSummary* summary =
6067 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 6105 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
6068 summary->set_in(0, Location::RequiresFpuRegister()); 6106 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
6069 summary->set_out(0, Location::RequiresFpuRegister()); 6107 Location::RequiresRegister()));
6070 if (FLAG_throw_on_javascript_int_overflow) { 6108 summary->set_out(0, Location::Pair(Location::RequiresRegister(),
6071 summary->set_temp(0, Location::RequiresRegister()); 6109 Location::RequiresRegister()));
6072 summary->set_temp(1, Location::RequiresRegister());
6073 }
6074 return summary; 6110 return summary;
6075 } 6111 }
6076 6112
6077 6113
6078 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 6114 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
6079 ASSERT(op_kind() == Token::kBIT_NOT); 6115 ASSERT(op_kind() == Token::kBIT_NOT);
6080 const QRegister value = locs()->in(0).fpu_reg(); 6116 PairLocation* left_pair = locs()->in(0).AsPairLocation();
6081 const QRegister out = locs()->out(0).fpu_reg(); 6117 Register left_lo = left_pair->At(0).reg();
6118 Register left_hi = left_pair->At(1).reg();
6119
6120 PairLocation* out_pair = locs()->out(0).AsPairLocation();
6121 Register out_lo = out_pair->At(0).reg();
6122 Register out_hi = out_pair->At(1).reg();
6123
6082 Label* deopt = NULL; 6124 Label* deopt = NULL;
6125
6083 if (FLAG_throw_on_javascript_int_overflow) { 6126 if (FLAG_throw_on_javascript_int_overflow) {
6084 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp); 6127 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp);
6085 } 6128 }
6086 __ vmvnq(out, value); 6129 __ mvn(out_lo, ShifterOperand(left_lo));
6130 __ mvn(out_hi, ShifterOperand(left_hi));
6087 if (FLAG_throw_on_javascript_int_overflow) { 6131 if (FLAG_throw_on_javascript_int_overflow) {
6088 const Register tmp1 = locs()->temp(0).reg(); 6132 EmitJavascriptIntOverflowCheck(compiler, deopt, out_lo, out_hi);
6089 const Register tmp2 = locs()->temp(1).reg();
6090 EmitJavascriptIntOverflowCheck(compiler, deopt, out, tmp1, tmp2);
6091 } 6133 }
6092 } 6134 }
6093 6135
6094 6136
6095 LocationSummary* ThrowInstr::MakeLocationSummary(bool opt) const { 6137 LocationSummary* ThrowInstr::MakeLocationSummary(bool opt) const {
6096 return new LocationSummary(0, 0, LocationSummary::kCall); 6138 return new LocationSummary(0, 0, LocationSummary::kCall);
6097 } 6139 }
6098 6140
6099 6141
6100 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 6142 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
6290 compiler->GenerateCall(token_pos(), 6332 compiler->GenerateCall(token_pos(),
6291 &label, 6333 &label,
6292 PcDescriptors::kOther, 6334 PcDescriptors::kOther,
6293 locs()); 6335 locs());
6294 __ Drop(ArgumentCount()); // Discard arguments. 6336 __ Drop(ArgumentCount()); // Discard arguments.
6295 } 6337 }
6296 6338
6297 } // namespace dart 6339 } // namespace dart
6298 6340
6299 #endif // defined TARGET_ARCH_ARM 6341 #endif // defined TARGET_ARCH_ARM
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698