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

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 361 matching lines...) Expand 10 before | Expand all | Expand 10 after
372 default: 372 default:
373 UNREACHABLE(); 373 UNREACHABLE();
374 return VS; 374 return VS;
375 } 375 }
376 } 376 }
377 377
378 378
379 LocationSummary* EqualityCompareInstr::MakeLocationSummary(bool opt) const { 379 LocationSummary* EqualityCompareInstr::MakeLocationSummary(bool opt) const {
380 const intptr_t kNumInputs = 2; 380 const intptr_t kNumInputs = 2;
381 if (operation_cid() == kMintCid) { 381 if (operation_cid() == kMintCid) {
382 const intptr_t kNumTemps = 3; 382 const intptr_t kNumTemps = 0;
383 LocationSummary* locs = 383 LocationSummary* locs =
384 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 384 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
385 locs->set_in(0, Location::RequiresFpuRegister()); 385 locs->set_in(0, Location::Pair(Location::RequiresRegister(),
386 locs->set_in(1, Location::RequiresFpuRegister()); 386 Location::RequiresRegister()));
387 locs->set_temp(0, Location::RequiresFpuRegister()); 387 locs->set_in(1, Location::Pair(Location::RequiresRegister(),
388 locs->set_temp(1, Location::RequiresRegister()); 388 Location::RequiresRegister()));
389 locs->set_temp(2, Location::RequiresRegister());
390 locs->set_out(0, Location::RequiresRegister()); 389 locs->set_out(0, Location::RequiresRegister());
391 return locs; 390 return locs;
392 } 391 }
393 if (operation_cid() == kDoubleCid) { 392 if (operation_cid() == kDoubleCid) {
394 const intptr_t kNumTemps = 0; 393 const intptr_t kNumTemps = 0;
395 LocationSummary* locs = 394 LocationSummary* locs =
396 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 395 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
397 locs->set_in(0, Location::RequiresFpuRegister()); 396 locs->set_in(0, Location::RequiresFpuRegister());
398 locs->set_in(1, Location::RequiresFpuRegister()); 397 locs->set_in(1, Location::RequiresFpuRegister());
399 locs->set_out(0, Location::RequiresRegister()); 398 locs->set_out(0, Location::RequiresRegister());
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
507 UNREACHABLE(); 506 UNREACHABLE();
508 return VS; 507 return VS;
509 } 508 }
510 } 509 }
511 510
512 511
513 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, 512 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler,
514 LocationSummary* locs, 513 LocationSummary* locs,
515 Token::Kind kind) { 514 Token::Kind kind) {
516 ASSERT(Token::IsEqualityOperator(kind)); 515 ASSERT(Token::IsEqualityOperator(kind));
517 QRegister left = locs->in(0).fpu_reg(); 516 PairLocation* left_pair = locs->in(0).AsPairLocation();
518 QRegister right = locs->in(1).fpu_reg(); 517 Register left1 = left_pair->At(0).reg();
zra 2014/05/14 18:27:41 optional: rename to {left, right}_{lo, hi}.
Cutch 2014/05/15 18:26:08 Done.
519 QRegister tmpq = locs->temp(0).fpu_reg(); 518 Register left2 = left_pair->At(1).reg();
520 Register tmp_lo = locs->temp(1).reg(); 519 PairLocation* right_pair = locs->in(1).AsPairLocation();
521 Register tmp_hi = locs->temp(2).reg(); 520 Register right1 = right_pair->At(0).reg();
521 Register right2 = right_pair->At(1).reg();
522 522
523 __ vceqqi(kWord, tmpq, left, right); 523 Label done;
524 __ vmovrrd(tmp_lo, tmp_hi, EvenDRegisterOf(tmpq));
525 // tmp_lo and tmp_hi must both be 0xffffffff.
526 __ and_(tmp_lo, tmp_lo, ShifterOperand(tmp_hi));
527 524
528 Condition true_condition = TokenKindToMintCondition(kind); 525 // Compare lower.
529 __ CompareImmediate(tmp_lo, 0xffffffff); 526 __ cmp(left1, ShifterOperand(right1));
530 return true_condition; 527 __ b(&done, NE);
528 // Lower is equal, compare upper.
529 __ cmp(left2, ShifterOperand(right2));
zra 2014/05/14 18:27:41 Remove branch, instead: __ cmp(left2, ShifterOpera
Cutch 2014/05/15 18:26:08 Done but I think you meant EQ instead of NE.
zra 2014/05/15 18:30:45 Yes, you're right.
530 __ Bind(&done);
531 return TokenKindToMintCondition(kind);
531 } 532 }
532 533
533 534
534 static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, 535 static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler,
535 LocationSummary* locs, 536 LocationSummary* locs,
536 Token::Kind kind) { 537 Token::Kind kind) {
537 QRegister left = locs->in(0).fpu_reg(); 538 PairLocation* left_pair = locs->in(0).AsPairLocation();
538 QRegister right = locs->in(1).fpu_reg(); 539 Register left1 = left_pair->At(0).reg();
zra 2014/05/14 18:27:41 optional: rename to {left, right}_{lo, hi}.
Cutch 2014/05/15 18:26:08 Done.
539 DRegister dleft0 = EvenDRegisterOf(left); 540 Register left2 = left_pair->At(1).reg();
540 DRegister dright0 = EvenDRegisterOf(right); 541 PairLocation* right_pair = locs->in(1).AsPairLocation();
541 SRegister sleft0 = EvenSRegisterOf(dleft0); 542 Register right1 = right_pair->At(0).reg();
542 SRegister sleft1 = OddSRegisterOf(dleft0); 543 Register right2 = right_pair->At(1).reg();
543 SRegister sright0 = EvenSRegisterOf(dright0);
544 SRegister sright1 = OddSRegisterOf(dright0);
545 544
546 Register tmp_left = locs->temp(0).reg(); 545 Register out = locs->temp(0).reg();
547 Register tmp_right = locs->temp(1).reg();
548 546
549 // 64-bit comparison 547 // 64-bit comparison
550 Condition hi_true_cond, hi_false_cond, lo_false_cond; 548 Condition hi_true_cond, hi_false_cond, lo_false_cond;
551 switch (kind) { 549 switch (kind) {
552 case Token::kLT: 550 case Token::kLT:
553 case Token::kLTE: 551 case Token::kLTE:
554 hi_true_cond = LT; 552 hi_true_cond = LT;
555 hi_false_cond = GT; 553 hi_false_cond = GT;
556 lo_false_cond = (kind == Token::kLT) ? CS : HI; 554 lo_false_cond = (kind == Token::kLT) ? CS : HI;
557 break; 555 break;
558 case Token::kGT: 556 case Token::kGT:
559 case Token::kGTE: 557 case Token::kGTE:
560 hi_true_cond = GT; 558 hi_true_cond = GT;
561 hi_false_cond = LT; 559 hi_false_cond = LT;
562 lo_false_cond = (kind == Token::kGT) ? LS : CC; 560 lo_false_cond = (kind == Token::kGT) ? LS : CC;
563 break; 561 break;
564 default: 562 default:
565 UNREACHABLE(); 563 UNREACHABLE();
566 hi_true_cond = hi_false_cond = lo_false_cond = VS; 564 hi_true_cond = hi_false_cond = lo_false_cond = VS;
567 } 565 }
568 566
569 Label is_true, is_false, done; 567 Label is_true, is_false, done;
570 __ vmovrs(tmp_left, sleft1); 568 // Compare upper halves first.
571 __ vmovrs(tmp_right, sright1); 569 __ cmp(left2, ShifterOperand(right2));
572 __ cmp(tmp_left, ShifterOperand(tmp_right));
573 __ b(&is_false, hi_false_cond); 570 __ b(&is_false, hi_false_cond);
574 __ b(&is_true, hi_true_cond); 571 __ b(&is_true, hi_true_cond);
zra 2014/05/14 18:27:41 Instead, to avoid so many branches: __ cmp(left2,
Cutch 2014/05/15 18:26:08 Done.
575 572
576 __ vmovrs(tmp_left, sleft0); 573 // If upper is equal, compare lower half.
577 __ vmovrs(tmp_right, sright0); 574 __ cmp(left1, ShifterOperand(right1));
578 __ cmp(tmp_left, ShifterOperand(tmp_right));
579 __ b(&is_false, lo_false_cond); 575 __ b(&is_false, lo_false_cond);
576
580 // Else is true. 577 // Else is true.
581 __ b(&is_true); 578 __ b(&is_true);
582 579
583 __ Bind(&is_false); 580 __ Bind(&is_false);
584 __ LoadImmediate(tmp_left, 0); 581 __ LoadImmediate(out, 0);
585 __ b(&done); 582 __ b(&done);
586 __ Bind(&is_true); 583 __ Bind(&is_true);
587 __ LoadImmediate(tmp_left, 1); 584 __ LoadImmediate(out, 1);
588 __ Bind(&done); 585 __ Bind(&done);
589 return NegateCondition(lo_false_cond); 586 return NegateCondition(lo_false_cond);
590 } 587 }
591 588
592 589
593 static Condition TokenKindToDoubleCondition(Token::Kind kind) { 590 static Condition TokenKindToDoubleCondition(Token::Kind kind) {
594 switch (kind) { 591 switch (kind) {
595 case Token::kEQ: return EQ; 592 case Token::kEQ: return EQ;
596 case Token::kNE: return NE; 593 case Token::kNE: return NE;
597 case Token::kLT: return LT; 594 case Token::kLT: return LT;
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
785 __ Bind(&is_true); 782 __ Bind(&is_true);
786 __ LoadObject(result_reg, Bool::True()); 783 __ LoadObject(result_reg, Bool::True());
787 __ Bind(&done); 784 __ Bind(&done);
788 } 785 }
789 786
790 787
791 LocationSummary* RelationalOpInstr::MakeLocationSummary(bool opt) const { 788 LocationSummary* RelationalOpInstr::MakeLocationSummary(bool opt) const {
792 const intptr_t kNumInputs = 2; 789 const intptr_t kNumInputs = 2;
793 const intptr_t kNumTemps = 0; 790 const intptr_t kNumTemps = 0;
794 if (operation_cid() == kMintCid) { 791 if (operation_cid() == kMintCid) {
795 const intptr_t kNumTemps = 2; 792 const intptr_t kNumTemps = 1;
796 LocationSummary* locs = 793 LocationSummary* locs =
797 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 794 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
798 locs->set_in(0, Location::RequiresFpuRegister()); 795 locs->set_in(0, Location::Pair(Location::RequiresRegister(),
799 locs->set_in(1, Location::RequiresFpuRegister()); 796 Location::RequiresRegister()));
797 locs->set_in(1, Location::Pair(Location::RequiresRegister(),
798 Location::RequiresRegister()));
800 locs->set_temp(0, Location::RequiresRegister()); 799 locs->set_temp(0, Location::RequiresRegister());
801 locs->set_temp(1, Location::RequiresRegister());
802 locs->set_out(0, Location::RequiresRegister()); 800 locs->set_out(0, Location::RequiresRegister());
803 return locs; 801 return locs;
804 } 802 }
805 if (operation_cid() == kDoubleCid) { 803 if (operation_cid() == kDoubleCid) {
806 LocationSummary* summary = 804 LocationSummary* summary =
807 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 805 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
808 summary->set_in(0, Location::RequiresFpuRegister()); 806 summary->set_in(0, Location::RequiresFpuRegister());
809 summary->set_in(1, Location::RequiresFpuRegister()); 807 summary->set_in(1, Location::RequiresFpuRegister());
810 summary->set_out(0, Location::RequiresRegister()); 808 summary->set_out(0, Location::RequiresRegister());
811 return summary; 809 return summary;
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after
1141 (representation() == kUnboxedInt32x4) || 1139 (representation() == kUnboxedInt32x4) ||
1142 (representation() == kUnboxedFloat64x2)) { 1140 (representation() == kUnboxedFloat64x2)) {
1143 if (class_id() == kTypedDataFloat32ArrayCid) { 1141 if (class_id() == kTypedDataFloat32ArrayCid) {
1144 // Need register <= Q7 for float operations. 1142 // Need register <= Q7 for float operations.
1145 // TODO(fschneider): Add a register policy to specify a subset of 1143 // TODO(fschneider): Add a register policy to specify a subset of
1146 // registers. 1144 // registers.
1147 locs->set_out(0, Location::FpuRegisterLocation(Q7)); 1145 locs->set_out(0, Location::FpuRegisterLocation(Q7));
1148 } else { 1146 } else {
1149 locs->set_out(0, Location::RequiresFpuRegister()); 1147 locs->set_out(0, Location::RequiresFpuRegister());
1150 } 1148 }
1149 } else if (representation() == kUnboxedMint) {
1150 locs->set_out(0, Location::Pair(Location::RequiresRegister(),
1151 Location::RequiresRegister()));
1151 } else { 1152 } else {
1153 ASSERT(representation() == kTagged);
1152 locs->set_out(0, Location::RequiresRegister()); 1154 locs->set_out(0, Location::RequiresRegister());
1153 } 1155 }
1154 return locs; 1156 return locs;
1155 } 1157 }
1156 1158
1157 1159
1158 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1160 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1159 if ((representation() == kUnboxedDouble) || 1161 if ((representation() == kUnboxedDouble) ||
1160 (representation() == kUnboxedMint) ||
1161 (representation() == kUnboxedFloat32x4) || 1162 (representation() == kUnboxedFloat32x4) ||
1162 (representation() == kUnboxedInt32x4) || 1163 (representation() == kUnboxedInt32x4) ||
1163 (representation() == kUnboxedFloat64x2)) { 1164 (representation() == kUnboxedFloat64x2)) {
1164 Register array = locs()->in(0).reg(); 1165 Register array = locs()->in(0).reg();
1165 Register idx = locs()->in(1).reg(); 1166 Register idx = locs()->in(1).reg();
1166 switch (index_scale()) { 1167 switch (index_scale()) {
1167 case 1: 1168 case 1:
1168 __ add(idx, array, ShifterOperand(idx, ASR, kSmiTagSize)); 1169 __ add(idx, array, ShifterOperand(idx, ASR, kSmiTagSize));
1169 break; 1170 break;
1170 case 4: 1171 case 4:
(...skipping 11 matching lines...) Expand all
1182 } 1183 }
1183 if (!IsExternal()) { 1184 if (!IsExternal()) {
1184 ASSERT(this->array()->definition()->representation() == kTagged); 1185 ASSERT(this->array()->definition()->representation() == kTagged);
1185 __ AddImmediate(idx, 1186 __ AddImmediate(idx,
1186 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag); 1187 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag);
1187 } 1188 }
1188 Address element_address(idx); 1189 Address element_address(idx);
1189 const QRegister result = locs()->out(0).fpu_reg(); 1190 const QRegister result = locs()->out(0).fpu_reg();
1190 const DRegister dresult0 = EvenDRegisterOf(result); 1191 const DRegister dresult0 = EvenDRegisterOf(result);
1191 switch (class_id()) { 1192 switch (class_id()) {
1192 case kTypedDataInt32ArrayCid:
1193 __ veorq(result, result, result);
1194 __ ldr(TMP, element_address);
1195 // Re-use the index register so we don't have to require a low-numbered
1196 // Q register.
1197 // Sign-extend into idx.
1198 __ Asr(idx, TMP, 31);
1199 __ vmovdrr(dresult0, TMP, idx);
1200 break;
1201 case kTypedDataUint32ArrayCid:
1202 __ veorq(result, result, result);
1203 __ ldr(TMP, element_address);
1204 // Re-use the index register so we don't have to require a low-numbered
1205 // Q register.
1206 __ LoadImmediate(idx, 0);
1207 __ vmovdrr(dresult0, TMP, idx);
1208 break;
1209 case kTypedDataFloat32ArrayCid: 1193 case kTypedDataFloat32ArrayCid:
1210 // Load single precision float. 1194 // Load single precision float.
1211 // vldrs does not support indexed addressing. 1195 // vldrs does not support indexed addressing.
1212 __ vldrs(EvenSRegisterOf(dresult0), element_address); 1196 __ vldrs(EvenSRegisterOf(dresult0), element_address);
1213 break; 1197 break;
1214 case kTypedDataFloat64ArrayCid: 1198 case kTypedDataFloat64ArrayCid:
1215 // vldrd does not support indexed addressing. 1199 // vldrd does not support indexed addressing.
1216 __ vldrd(dresult0, element_address); 1200 __ vldrd(dresult0, element_address);
1217 break; 1201 break;
1218 case kTypedDataFloat64x2ArrayCid: 1202 case kTypedDataFloat64x2ArrayCid:
1219 case kTypedDataInt32x4ArrayCid: 1203 case kTypedDataInt32x4ArrayCid:
1220 case kTypedDataFloat32x4ArrayCid: 1204 case kTypedDataFloat32x4ArrayCid:
1221 __ vldmd(IA, idx, dresult0, 2); 1205 __ vldmd(IA, idx, dresult0, 2);
1222 break; 1206 break;
1207 default:
1208 UNREACHABLE();
1223 } 1209 }
1224 return; 1210 return;
1225 } 1211 }
1226 1212
1227 Register array = locs()->in(0).reg(); 1213 Register array = locs()->in(0).reg();
1228 Location index = locs()->in(1); 1214 Location index = locs()->in(1);
1229 1215
1230 Address element_address(kNoRegister, 0); 1216 Address element_address(kNoRegister, 0);
1231 ASSERT(index.IsRegister()); // TODO(regis): Revisit. 1217 ASSERT(index.IsRegister()); // TODO(regis): Revisit.
1232 // Note that index is expected smi-tagged, (i.e, times 2) for all arrays 1218 // Note that index is expected smi-tagged, (i.e, times 2) for all arrays
(...skipping 23 matching lines...) Expand all
1256 default: 1242 default:
1257 UNREACHABLE(); 1243 UNREACHABLE();
1258 } 1244 }
1259 1245
1260 if (!IsExternal()) { 1246 if (!IsExternal()) {
1261 ASSERT(this->array()->definition()->representation() == kTagged); 1247 ASSERT(this->array()->definition()->representation() == kTagged);
1262 __ AddImmediate(index.reg(), 1248 __ AddImmediate(index.reg(),
1263 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag); 1249 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag);
1264 } 1250 }
1265 element_address = Address(array, index.reg(), LSL, 0); 1251 element_address = Address(array, index.reg(), LSL, 0);
1252
1253 if (representation() == kUnboxedMint) {
1254 ASSERT(locs()->out(0).IsPairLocation());
1255 PairLocation* result_pair = locs()->out(0).AsPairLocation();
1256 Register result1 = result_pair->At(0).reg();
1257 Register result2 = result_pair->At(1).reg();
1258 switch (class_id()) {
1259 case kTypedDataInt32ArrayCid:
1260 // Load low word.
1261 __ ldr(result1, element_address);
1262 // Sign extend into high word.
1263 __ SignFill(result2, result1);
1264 break;
1265 case kTypedDataUint32ArrayCid:
1266 // Load low word.
1267 __ ldr(result1, element_address);
1268 // Zero high word.
1269 __ eor(result2, result2, ShifterOperand(result2));
1270 break;
1271 default:
1272 UNREACHABLE();
1273 break;
1274 }
1275 return;
1276 }
1277
1278 ASSERT(representation() == kTagged);
1279
1266 Register result = locs()->out(0).reg(); 1280 Register result = locs()->out(0).reg();
1267 switch (class_id()) { 1281 switch (class_id()) {
1268 case kTypedDataInt8ArrayCid: 1282 case kTypedDataInt8ArrayCid:
1269 ASSERT(index_scale() == 1); 1283 ASSERT(index_scale() == 1);
1270 __ ldrsb(result, element_address); 1284 __ ldrsb(result, element_address);
1271 __ SmiTag(result); 1285 __ SmiTag(result);
1272 break; 1286 break;
1273 case kTypedDataUint8ArrayCid: 1287 case kTypedDataUint8ArrayCid:
1274 case kTypedDataUint8ClampedArrayCid: 1288 case kTypedDataUint8ClampedArrayCid:
1275 case kExternalTypedDataUint8ArrayCid: 1289 case kExternalTypedDataUint8ArrayCid:
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
1373 case kTypedDataInt8ArrayCid: 1387 case kTypedDataInt8ArrayCid:
1374 case kTypedDataUint8ArrayCid: 1388 case kTypedDataUint8ArrayCid:
1375 case kTypedDataUint8ClampedArrayCid: 1389 case kTypedDataUint8ClampedArrayCid:
1376 case kOneByteStringCid: 1390 case kOneByteStringCid:
1377 case kTypedDataInt16ArrayCid: 1391 case kTypedDataInt16ArrayCid:
1378 case kTypedDataUint16ArrayCid: 1392 case kTypedDataUint16ArrayCid:
1379 locs->set_in(2, Location::WritableRegister()); 1393 locs->set_in(2, Location::WritableRegister());
1380 break; 1394 break;
1381 case kTypedDataInt32ArrayCid: 1395 case kTypedDataInt32ArrayCid:
1382 case kTypedDataUint32ArrayCid: 1396 case kTypedDataUint32ArrayCid:
1383 // Mints are stored in Q registers. For smis, use a writable register 1397 // For smis, use a writable register because the value must be untagged
1384 // because the value must be untagged before storing. 1398 // before storing. Mints are stored in register pairs.
1385 locs->set_in(2, value()->IsSmiValue() 1399 if (value()->IsSmiValue()) {
1386 ? Location::WritableRegister() 1400 locs->set_in(2, Location::WritableRegister());
1387 : Location::FpuRegisterLocation(Q7)); 1401 } else {
1402 // We only move the lower 32-bits so we don't care where the high bits
1403 // are located.
1404 locs->set_in(2, Location::Pair(Location::RequiresRegister(),
1405 Location::Any()));
1406 }
1388 break; 1407 break;
1389 case kTypedDataFloat32ArrayCid: 1408 case kTypedDataFloat32ArrayCid:
1390 // Need low register (<= Q7). 1409 // Need low register (<= Q7).
1391 locs->set_in(2, Location::FpuRegisterLocation(Q7)); 1410 locs->set_in(2, Location::FpuRegisterLocation(Q7));
1392 break; 1411 break;
1393 case kTypedDataFloat64ArrayCid: // TODO(srdjan): Support Float64 constants. 1412 case kTypedDataFloat64ArrayCid: // TODO(srdjan): Support Float64 constants.
1394 case kTypedDataInt32x4ArrayCid: 1413 case kTypedDataInt32x4ArrayCid:
1395 case kTypedDataFloat32x4ArrayCid: 1414 case kTypedDataFloat32x4ArrayCid:
1396 case kTypedDataFloat64x2ArrayCid: 1415 case kTypedDataFloat64x2ArrayCid:
1397 locs->set_in(2, Location::RequiresFpuRegister()); 1416 locs->set_in(2, Location::RequiresFpuRegister());
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
1508 } 1527 }
1509 case kTypedDataInt32ArrayCid: 1528 case kTypedDataInt32ArrayCid:
1510 case kTypedDataUint32ArrayCid: { 1529 case kTypedDataUint32ArrayCid: {
1511 if (value()->IsSmiValue()) { 1530 if (value()->IsSmiValue()) {
1512 ASSERT(RequiredInputRepresentation(2) == kTagged); 1531 ASSERT(RequiredInputRepresentation(2) == kTagged);
1513 Register value = locs()->in(2).reg(); 1532 Register value = locs()->in(2).reg();
1514 __ SmiUntag(value); 1533 __ SmiUntag(value);
1515 __ str(value, element_address); 1534 __ str(value, element_address);
1516 } else { 1535 } else {
1517 ASSERT(RequiredInputRepresentation(2) == kUnboxedMint); 1536 ASSERT(RequiredInputRepresentation(2) == kUnboxedMint);
1518 QRegister value = locs()->in(2).fpu_reg(); 1537 PairLocation* value_pair = locs()->in(2).AsPairLocation();
1519 ASSERT(value == Q7); 1538 Register value1 = value_pair->At(0).reg();
1520 __ vmovrs(TMP, EvenSRegisterOf(EvenDRegisterOf(value))); 1539 __ str(value1, element_address);
1521 __ str(TMP, element_address);
1522 } 1540 }
1523 break; 1541 break;
1524 } 1542 }
1525 case kTypedDataFloat32ArrayCid: { 1543 case kTypedDataFloat32ArrayCid: {
1526 SRegister value = 1544 SRegister value =
1527 EvenSRegisterOf(EvenDRegisterOf(locs()->in(2).fpu_reg())); 1545 EvenSRegisterOf(EvenDRegisterOf(locs()->in(2).fpu_reg()));
1528 __ add(index.reg(), index.reg(), ShifterOperand(array)); 1546 __ add(index.reg(), index.reg(), ShifterOperand(array));
1529 __ StoreSToOffset(value, index.reg(), 0); 1547 __ StoreSToOffset(value, index.reg(), 0);
1530 break; 1548 break;
1531 } 1549 }
(...skipping 4060 matching lines...) Expand 10 before | Expand all | Expand 10 after
5592 Register length = length_loc.reg(); 5610 Register length = length_loc.reg();
5593 Register index = index_loc.reg(); 5611 Register index = index_loc.reg();
5594 __ cmp(index, ShifterOperand(length)); 5612 __ cmp(index, ShifterOperand(length));
5595 __ b(deopt, CS); 5613 __ b(deopt, CS);
5596 } 5614 }
5597 } 5615 }
5598 5616
5599 5617
5600 static void EmitJavascriptIntOverflowCheck(FlowGraphCompiler* compiler, 5618 static void EmitJavascriptIntOverflowCheck(FlowGraphCompiler* compiler,
5601 Label* overflow, 5619 Label* overflow,
5602 QRegister result, 5620 Register result_lo,
5603 Register tmp_hi, Register tmp_lo) { 5621 Register result_hi) {
5604 __ vmovrrd(tmp_lo, tmp_hi, EvenDRegisterOf(result));
5605 // Compare upper half. 5622 // Compare upper half.
5606 Label check_lower; 5623 Label check_lower;
5607 __ CompareImmediate(tmp_hi, 0x00200000); 5624 __ CompareImmediate(result_hi, 0x00200000);
5608 __ b(overflow, GT); 5625 __ b(overflow, GT);
5609 __ b(&check_lower, NE); 5626 __ b(&check_lower, NE);
5610 5627
5611 __ CompareImmediate(tmp_lo, 0); 5628 __ CompareImmediate(result_lo, 0);
5612 __ b(overflow, HI); 5629 __ b(overflow, HI);
5613 5630
5614 __ Bind(&check_lower); 5631 __ Bind(&check_lower);
5615 __ CompareImmediate(tmp_hi, -0x00200000); 5632 __ CompareImmediate(result_hi, -0x00200000);
5616 __ b(overflow, LT); 5633 __ b(overflow, LT);
5617 // Anything in the lower part would make the number bigger than the lower 5634 // Anything in the lower part would make the number bigger than the lower
5618 // bound, so we are done. 5635 // bound, so we are done.
5619 } 5636 }
5620 5637
5621 5638
5622 LocationSummary* UnboxIntegerInstr::MakeLocationSummary(bool opt) const { 5639 LocationSummary* UnboxIntegerInstr::MakeLocationSummary(bool opt) const {
5623 const intptr_t kNumInputs = 1; 5640 const intptr_t kNumInputs = 1;
5624 const intptr_t value_cid = value()->Type()->ToCid(); 5641 const intptr_t kNumTemps = 1;
5625 const bool needs_writable_input = (value_cid != kMintCid);
5626 const bool needs_temp = (value_cid != kMintCid);
5627 const intptr_t kNumTemps = needs_temp ? 1 : 0;
5628 LocationSummary* summary = 5642 LocationSummary* summary =
5629 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 5643 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
5630 summary->set_in(0, needs_writable_input 5644 summary->set_in(0, Location::RequiresRegister());
5631 ? Location::WritableRegister() 5645 summary->set_temp(0, Location::RequiresRegister());
5632 : Location::RequiresRegister()); 5646 summary->set_out(0, Location::Pair(Location::RequiresRegister(),
5633 if (needs_temp) { 5647 Location::RequiresRegister()));
5634 summary->set_temp(0, Location::RequiresRegister());
5635 }
5636 summary->set_out(0, Location::RequiresFpuRegister());
5637 return summary; 5648 return summary;
5638 } 5649 }
5639 5650
5640 5651
5641 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5652 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5642 const intptr_t value_cid = value()->Type()->ToCid(); 5653 const intptr_t value_cid = value()->Type()->ToCid();
5643 const Register value = locs()->in(0).reg(); 5654 const Register value = locs()->in(0).reg();
5644 const QRegister result = locs()->out(0).fpu_reg(); 5655 PairLocation* result_pair = locs()->out(0).AsPairLocation();
5656 Register result1 = result_pair->At(0).reg();
5657 Register result2 = result_pair->At(1).reg();
5658 ASSERT(value != result1);
5659 ASSERT(value != result2);
5645 5660
5646 __ Comment("UnboxIntegerInstr"); 5661 __ Comment("UnboxIntegerInstr");
5647 __ veorq(result, result, result);
5648 if (value_cid == kMintCid) { 5662 if (value_cid == kMintCid) {
5649 __ LoadDFromOffset(EvenDRegisterOf(result), value, 5663 // Load low word.
5650 Mint::value_offset() - kHeapObjectTag); 5664 __ LoadFromOffset(kWord,
5665 result1,
5666 value,
5667 Mint::value_offset() - kHeapObjectTag);
5668 // Load high word.
5669 __ LoadFromOffset(kWord,
5670 result2,
5671 value,
5672 Mint::value_offset() - kHeapObjectTag + kWordSize);
5651 } else if (value_cid == kSmiCid) { 5673 } else if (value_cid == kSmiCid) {
5652 Register temp = locs()->temp(0).reg(); 5674 // Load Smi into result1.
5653 __ SmiUntag(value); 5675 __ mov(result1, ShifterOperand(value));
5654 // Sign extend value into temp. 5676 // Untag.
5655 __ Asr(temp, value, 31); 5677 __ SmiUntag(result1);
5656 __ vmovdrr(EvenDRegisterOf(result), value, temp); 5678 __ SignFill(result2, result1);
5657 } else { 5679 } else {
5658 Register temp = locs()->temp(0).reg(); 5680 Register temp = locs()->temp(0).reg();
5659 Label* deopt = compiler->AddDeoptStub(deopt_id_, 5681 Label* deopt = compiler->AddDeoptStub(deopt_id_,
5660 ICData::kDeoptUnboxInteger); 5682 ICData::kDeoptUnboxInteger);
5661 Label is_smi, done; 5683 Label is_smi, done;
5662 __ tst(value, ShifterOperand(kSmiTagMask)); 5684 __ tst(value, ShifterOperand(kSmiTagMask));
5663 __ b(&is_smi, EQ); 5685 __ b(&is_smi, EQ);
5664 __ CompareClassId(value, kMintCid, temp); 5686 __ CompareClassId(value, kMintCid, temp);
5665 __ b(deopt, NE); 5687 __ b(deopt, NE);
5666 5688
5667 // It's a Mint. 5689 // It's a Mint.
5668 __ LoadDFromOffset(EvenDRegisterOf(result), value, 5690 // Load low word.
5669 Mint::value_offset() - kHeapObjectTag); 5691 __ LoadFromOffset(kWord,
5692 result1,
5693 value,
5694 Mint::value_offset() - kHeapObjectTag);
5695 // Load high word.
5696 __ LoadFromOffset(kWord,
5697 result2,
5698 value,
5699 Mint::value_offset() - kHeapObjectTag + kWordSize);
5670 __ b(&done); 5700 __ b(&done);
5671 5701
5672 // It's a Smi. 5702 // It's a Smi.
5673 __ Bind(&is_smi); 5703 __ Bind(&is_smi);
5674 __ SmiUntag(value); 5704 // Load Smi into result1.
5675 // Sign extend into temp. 5705 __ mov(result1, ShifterOperand(value));
5676 __ Asr(temp, value, 31); 5706 // Untag.
5677 __ vmovdrr(EvenDRegisterOf(result), value, temp); 5707 __ SmiUntag(result1);
5708 // Sign extend result1 into result2.
5709 __ SignFill(result2, result1);
5678 __ Bind(&done); 5710 __ Bind(&done);
5679 } 5711 }
5680 } 5712 }
5681 5713
5682 5714
5683 LocationSummary* BoxIntegerInstr::MakeLocationSummary(bool opt) const { 5715 LocationSummary* BoxIntegerInstr::MakeLocationSummary(bool opt) const {
5684 const intptr_t kNumInputs = 1; 5716 const intptr_t kNumInputs = 1;
5685 const intptr_t kNumTemps = 2; 5717 const intptr_t kNumTemps = 1;
5686 LocationSummary* summary = 5718 LocationSummary* summary =
5687 new LocationSummary(kNumInputs, 5719 new LocationSummary(kNumInputs,
5688 kNumTemps, 5720 kNumTemps,
5689 LocationSummary::kCallOnSlowPath); 5721 LocationSummary::kCallOnSlowPath);
5690 summary->set_in(0, Location::RequiresFpuRegister()); 5722 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
5723 Location::RequiresRegister()));
5691 summary->set_temp(0, Location::RequiresRegister()); 5724 summary->set_temp(0, Location::RequiresRegister());
5692 summary->set_temp(1, Location::RequiresRegister());
5693 summary->set_out(0, Location::RequiresRegister()); 5725 summary->set_out(0, Location::RequiresRegister());
5694 return summary; 5726 return summary;
5695 } 5727 }
5696 5728
5697 5729
5698 class BoxIntegerSlowPath : public SlowPathCode { 5730 class BoxIntegerSlowPath : public SlowPathCode {
5699 public: 5731 public:
5700 explicit BoxIntegerSlowPath(BoxIntegerInstr* instruction) 5732 explicit BoxIntegerSlowPath(BoxIntegerInstr* instruction)
5701 : instruction_(instruction) { } 5733 : instruction_(instruction) { }
5702 5734
(...skipping 21 matching lines...) Expand all
5724 } 5756 }
5725 5757
5726 private: 5758 private:
5727 BoxIntegerInstr* instruction_; 5759 BoxIntegerInstr* instruction_;
5728 }; 5760 };
5729 5761
5730 5762
5731 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5763 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5732 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this); 5764 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this);
5733 compiler->AddSlowPathCode(slow_path); 5765 compiler->AddSlowPathCode(slow_path);
5734 5766 PairLocation* value_pair = locs()->in(0).AsPairLocation();
5767 Register value1 = value_pair->At(0).reg();
zra 2014/05/14 18:27:41 optional: lo/hi instead of 1/2 as above
Cutch 2014/05/15 18:26:08 Done.
5768 Register value2 = value_pair->At(1).reg();
5769 Register tmp = locs()->temp(0).reg();
5735 Register out_reg = locs()->out(0).reg(); 5770 Register out_reg = locs()->out(0).reg();
5736 QRegister value = locs()->in(0).fpu_reg();
5737 DRegister dvalue0 = EvenDRegisterOf(value);
5738 Register lo = locs()->temp(0).reg();
5739 Register hi = locs()->temp(1).reg();
5740 5771
5741 // Unboxed operations produce smis or mint-sized values. 5772 // Unboxed operations produce smis or mint-sized values.
5742 // Check if value fits into a smi. 5773 // Check if value fits into a smi.
5743 __ Comment("BoxIntegerInstr"); 5774 __ Comment("BoxIntegerInstr");
5744 Label not_smi, done, maybe_pos_smi, maybe_neg_smi, is_smi; 5775 Label not_smi, done, maybe_pos_smi, maybe_neg_smi, is_smi;
5745 __ vmovrrd(lo, hi, dvalue0); 5776 // Check high word.
zra 2014/05/14 18:27:41 Can you rewrite this to mirror the ia32 implementa
Cutch 2014/05/15 18:26:08 I took a stab at this but kept getting test failur
zra 2014/05/15 18:30:45 sgtm
5746 __ CompareImmediate(hi, 0); 5777 __ CompareImmediate(value2, 0);
5747 __ b(&maybe_pos_smi, EQ); 5778 __ b(&maybe_pos_smi, EQ);
5748 5779
5749 __ CompareImmediate(hi, -1); 5780 __ CompareImmediate(value2, -1);
5750 __ b(&maybe_neg_smi, EQ); 5781 __ b(&maybe_neg_smi, EQ);
5751 __ b(&not_smi); 5782 __ b(&not_smi);
5752 5783
5753 __ Bind(&maybe_pos_smi); 5784 __ Bind(&maybe_pos_smi);
5754 __ CompareImmediate(lo, kSmiMax); 5785 __ CompareImmediate(value1, kSmiMax);
5755 __ b(&is_smi, LS); // unsigned lower or same. 5786 __ b(&is_smi, LS); // unsigned lower or same.
5756 __ b(&not_smi); 5787 __ b(&not_smi);
5757 5788
5758 __ Bind(&maybe_neg_smi); 5789 __ Bind(&maybe_neg_smi);
5759 __ CompareImmediate(lo, 0); 5790 __ CompareImmediate(value1, 0);
5760 __ b(&not_smi, GE); 5791 __ b(&not_smi, GE);
5761 __ CompareImmediate(lo, kSmiMin); 5792 __ CompareImmediate(value1, kSmiMin);
5762 __ b(&not_smi, LT); 5793 __ b(&not_smi, LT);
5763 5794
5764 // lo is a Smi. Tag it and return. 5795 // lo is a Smi. Tag it and return.
5765 __ Bind(&is_smi); 5796 __ Bind(&is_smi);
5766 __ SmiTag(lo); 5797 __ mov(out_reg, ShifterOperand(value1));
5767 __ mov(out_reg, ShifterOperand(lo)); 5798 __ SmiTag(out_reg);
5768 __ b(&done); 5799 __ b(&done);
5769 5800
5770 // Not a smi. Box it. 5801 // Not a smi. Box it.
5771 __ Bind(&not_smi); 5802 __ Bind(&not_smi);
5772 __ TryAllocate( 5803 __ TryAllocate(
5773 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()), 5804 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()),
5774 slow_path->entry_label(), 5805 slow_path->entry_label(),
5775 out_reg, 5806 out_reg,
5776 lo); 5807 tmp);
5777 __ Bind(slow_path->exit_label()); 5808 __ Bind(slow_path->exit_label());
5778 __ StoreDToOffset(dvalue0, out_reg, Mint::value_offset() - kHeapObjectTag); 5809 __ StoreToOffset(kWord,
5810 value1,
5811 out_reg,
5812 Mint::value_offset() - kHeapObjectTag);
5813 __ StoreToOffset(kWord,
5814 value2,
5815 out_reg,
5816 Mint::value_offset() - kHeapObjectTag + kWordSize);
5779 __ Bind(&done); 5817 __ Bind(&done);
5780 } 5818 }
5781 5819
5782 5820
5783 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(bool opt) const { 5821 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(bool opt) const {
5784 const intptr_t kNumInputs = 2; 5822 const intptr_t kNumInputs = 2;
5785 const intptr_t kNumTemps = 5823 const intptr_t kNumTemps = 0;
5786 FLAG_throw_on_javascript_int_overflow ? 2 : 0;
5787 LocationSummary* summary = 5824 LocationSummary* summary =
5788 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 5825 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
5789 summary->set_in(0, Location::RequiresFpuRegister()); 5826 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
5790 summary->set_in(1, Location::RequiresFpuRegister()); 5827 Location::RequiresRegister()));
5791 if (FLAG_throw_on_javascript_int_overflow) { 5828 summary->set_in(1, Location::Pair(Location::RequiresRegister(),
5792 summary->set_temp(0, Location::RequiresRegister()); 5829 Location::RequiresRegister()));
5793 summary->set_temp(1, Location::RequiresRegister()); 5830 summary->set_out(0, Location::Pair(Location::RequiresRegister(),
5794 } 5831 Location::RequiresRegister()));
5795 if ((op_kind() == Token::kADD) || (op_kind() == Token::kSUB)) {
5796 // Need another temp for checking for overflow.
5797 summary->AddTemp(Location::RequiresFpuRegister());
5798 summary->AddTemp(Location::FpuRegisterLocation(Q7));
5799 }
5800 summary->set_out(0, Location::RequiresFpuRegister());
5801 return summary; 5832 return summary;
5802 } 5833 }
5803 5834
5804 5835
5805 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5836 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5806 QRegister left = locs()->in(0).fpu_reg(); 5837 PairLocation* left_pair = locs()->in(0).AsPairLocation();
5807 QRegister right = locs()->in(1).fpu_reg(); 5838 Register left1 = left_pair->At(0).reg();
5808 QRegister out = locs()->out(0).fpu_reg(); 5839 Register left2 = left_pair->At(1).reg();
5840 PairLocation* right_pair = locs()->in(1).AsPairLocation();
5841 Register right1 = right_pair->At(0).reg();
5842 Register right2 = right_pair->At(1).reg();
5843 PairLocation* out_pair = locs()->out(0).AsPairLocation();
5844 Register out1 = out_pair->At(0).reg();
5845 Register out2 = out_pair->At(1).reg();
5809 5846
5810 Label* deopt = NULL; 5847 Label* deopt = NULL;
5811 if (FLAG_throw_on_javascript_int_overflow) { 5848 if (FLAG_throw_on_javascript_int_overflow) {
5812 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); 5849 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp);
5813 } 5850 }
5814 switch (op_kind()) { 5851 switch (op_kind()) {
5815 case Token::kBIT_AND: __ vandq(out, left, right); break; 5852 case Token::kBIT_AND: {
5816 case Token::kBIT_OR: __ vorrq(out, left, right); break; 5853 __ and_(out1, left1, ShifterOperand(right1));
5817 case Token::kBIT_XOR: __ veorq(out, left, right); break; 5854 __ and_(out2, left2, ShifterOperand(right2));
5855 }
5856 break;
5857 case Token::kBIT_OR: {
5858 __ orr(out1, left1, ShifterOperand(right1));
5859 __ orr(out2, left2, ShifterOperand(right2));
5860 }
5861 break;
5862 case Token::kBIT_XOR: {
5863 __ eor(out1, left1, ShifterOperand(right1));
5864 __ eor(out2, left2, ShifterOperand(right2));
5865 }
5866 break;
5818 case Token::kADD: 5867 case Token::kADD:
5819 case Token::kSUB: { 5868 case Token::kSUB: {
5820 const intptr_t tmpidx = FLAG_throw_on_javascript_int_overflow ? 2 : 0;
5821 QRegister tmp = locs()->temp(tmpidx).fpu_reg();
5822 QRegister ro = locs()->temp(tmpidx + 1).fpu_reg();
5823 ASSERT(ro == Q7);
5824 if (!FLAG_throw_on_javascript_int_overflow) { 5869 if (!FLAG_throw_on_javascript_int_overflow) {
5825 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); 5870 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp);
5826 } 5871 }
5827 if (op_kind() == Token::kADD) { 5872 if (op_kind() == Token::kADD) {
5828 __ vaddqi(kWordPair, out, left, right); 5873 __ adds(out1, left1, ShifterOperand(right1));
5874 __ adcs(out2, left2, ShifterOperand(right2));
5829 } else { 5875 } else {
5830 ASSERT(op_kind() == Token::kSUB); 5876 ASSERT(op_kind() == Token::kSUB);
5831 __ vsubqi(kWordPair, out, left, right); 5877 __ subs(out1, left1, ShifterOperand(right1));
5878 __ sbcs(out2, left2, ShifterOperand(right2));
5832 } 5879 }
5833 __ veorq(ro, out, left); 5880 // Deopt on overflow.
5834 __ veorq(tmp, left, right); 5881 __ b(deopt, VS);
5835 __ vandq(ro, tmp, ro);
5836 __ vmovrs(TMP, OddSRegisterOf(EvenDRegisterOf(ro)));
5837 // If TMP < 0, there was overflow.
5838 __ cmp(TMP, ShifterOperand(0));
5839 __ b(deopt, LT);
5840 break; 5882 break;
5841 } 5883 }
5842 default: UNREACHABLE(); break; 5884 default:
5885 UNREACHABLE();
5886 break;
5843 } 5887 }
5844 if (FLAG_throw_on_javascript_int_overflow) { 5888 if (FLAG_throw_on_javascript_int_overflow) {
5845 Register tmp1 = locs()->temp(0).reg(); 5889 EmitJavascriptIntOverflowCheck(compiler, deopt, out1, out2);
5846 Register tmp2 = locs()->temp(1).reg();
5847 EmitJavascriptIntOverflowCheck(compiler, deopt, out, tmp1, tmp2);
5848 } 5890 }
5849 } 5891 }
5850 5892
5851 5893
5852 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(bool opt) const { 5894 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(bool opt) const {
5853 const intptr_t kNumInputs = 2; 5895 const intptr_t kNumInputs = 2;
5854 const intptr_t kNumTemps = 5896 const intptr_t kNumTemps = 1;
5855 FLAG_throw_on_javascript_int_overflow ? 2 : 1;
5856 LocationSummary* summary = 5897 LocationSummary* summary =
5857 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 5898 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
5858 summary->set_in(0, Location::RequiresFpuRegister()); 5899 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
5900 Location::RequiresRegister()));
5859 summary->set_in(1, Location::WritableRegister()); 5901 summary->set_in(1, Location::WritableRegister());
5860 summary->set_temp(0, Location::FpuRegisterLocation(Q7)); 5902 summary->set_temp(0, Location::RequiresRegister());
5861 if (FLAG_throw_on_javascript_int_overflow) { 5903 summary->set_out(0, Location::Pair(Location::RequiresRegister(),
5862 summary->set_temp(1, Location::RequiresRegister()); 5904 Location::RequiresRegister()));
5863 }
5864 summary->set_out(0, Location::RequiresFpuRegister());
5865 return summary; 5905 return summary;
5866 } 5906 }
5867 5907
5868 5908
5869 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5909 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5870 QRegister value = locs()->in(0).fpu_reg(); 5910 PairLocation* left_pair = locs()->in(0).AsPairLocation();
5911 Register left1 = left_pair->At(0).reg();
5912 Register left2 = left_pair->At(1).reg();
5871 Register shift = locs()->in(1).reg(); 5913 Register shift = locs()->in(1).reg();
5872 QRegister temp = locs()->temp(0).fpu_reg(); 5914 PairLocation* out_pair = locs()->out(0).AsPairLocation();
5873 ASSERT(temp == Q7); 5915 Register out1 = out_pair->At(0).reg();
5874 QRegister out = locs()->out(0).fpu_reg(); 5916 Register out2 = out_pair->At(1).reg();
5875 DRegister dtemp0 = EvenDRegisterOf(temp); 5917 Register temp = locs()->temp(0).reg();
5876 SRegister stemp0 = EvenSRegisterOf(dtemp0);
5877 SRegister stemp1 = OddSRegisterOf(dtemp0);
5878 5918
5879 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp); 5919 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp);
5880 Label done; 5920 Label done, early_out;
5881 5921
5922 // Early out if shift is 0.
5882 __ CompareImmediate(shift, 0); 5923 __ CompareImmediate(shift, 0);
5883 __ vmovq(out, value); 5924 __ b(&early_out, EQ);
5884 __ b(&done, EQ); 5925
5926 // Untag shift count.
5885 __ SmiUntag(shift); 5927 __ SmiUntag(shift);
5886 5928
5887 // vshlq takes the shift value from low byte. Deopt if shift is 5929 // Deopt if shift is negative.
5888 // outside of [0, 63]. 5930 __ CompareImmediate(shift, 1);
5889 __ CompareImmediate(shift, 63);
5890 __ b(deopt, GT);
5891 __ CompareImmediate(shift, 0);
5892 __ b(deopt, LT); 5931 __ b(deopt, LT);
5893 5932
5894 __ veorq(temp, temp, temp); // Zero out temp. 5933 // Deopt if shift is larger than 32.
zra 2014/05/14 18:27:41 Are there funky things that happen for >= 32 as pa
Cutch 2014/05/15 18:26:08 Done.
5934 __ CompareImmediate(shift, 32);
5935 __ b(deopt, GT);
5936
5895 switch (op_kind()) { 5937 switch (op_kind()) {
5896 case Token::kSHR: { 5938 case Token::kSHR: {
5897 __ rsb(shift, shift, ShifterOperand(0)); // Negate shift. 5939 /*
5898 __ vmovsr(stemp0, shift); // Move the shift into the low S register. 5940 * Perform right shift, in pseudo C:
5899 __ vshlqi(kWordPair, out, value, temp); 5941 * temp = 32 - N;
5942 * temp = left2 <<L temp;
5943 * out1 = temp | (left1 L>> N);
5944 * out2 = left2 A>> N;
5945 */
5946 __ rsb(temp, shift, ShifterOperand(32));
5947 __ mov(temp, ShifterOperand(left2, LSL, temp));
5948 __ orr(out1, temp, ShifterOperand(left1, LSR, shift));
5949 __ mov(out2, ShifterOperand(left2, ASR, shift));
5950 // Finished.
5951 __ b(&done);
5900 break; 5952 break;
5901 } 5953 }
5902 case Token::kSHL: { 5954 case Token::kSHL: {
5903 __ vmovsr(stemp0, shift); // Move the shift into the low S register. 5955 /*
5904 __ vshlqu(kWordPair, out, value, temp); 5956 * Perform left shift, in pseudo C:
5957 * temp = 32 - N;
5958 * out2 = left2 <<L shift;
5959 * out2 = out2 | (left1 L>> temp);
5960 * out1 = left1 <<L shift;
5961 */
5962 __ rsb(temp, shift, ShifterOperand(32));
5963 __ mov(out2, ShifterOperand(left2, LSL, shift));
5964 __ orr(out2, out2, ShifterOperand(left1, LSR, temp));
5965 __ mov(out1, ShifterOperand(left1, LSL, shift));
5905 5966
5906 // check for overflow by shifting back and comparing. 5967 // Check for overflow.
5907 __ rsb(shift, shift, ShifterOperand(0)); 5968
5908 __ vmovsr(stemp0, shift); 5969 // Copy high word from output.
5909 __ vshlqi(kWordPair, temp, out, temp); 5970 __ mov(temp, ShifterOperand(out2));
5910 __ vceqqi(kWord, temp, temp, value); 5971 // Shift copy right.
5911 // Low 64 bits of temp should be all 1's, otherwise temp != value and 5972 __ Asr(temp, temp, shift);
5912 // we deopt. 5973 // Compare with high word from input.
5913 __ vmovrs(shift, stemp0); 5974 __ cmp(temp, ShifterOperand(left2));
5914 __ CompareImmediate(shift, -1); 5975 // Overflow if they aren't equal.
5915 __ b(deopt, NE); 5976 __ b(deopt, NE);
5916 __ vmovrs(shift, stemp1); 5977 // Finished.
5917 __ CompareImmediate(shift, -1); 5978 __ b(&done);
5918 __ b(deopt, NE);
5919 break; 5979 break;
5920 } 5980 }
5921 default: 5981 default:
5922 UNREACHABLE(); 5982 UNREACHABLE();
5923 break; 5983 break;
5924 } 5984 }
5925 5985
5986 __ Bind(&early_out);
5987 __ mov(out1, ShifterOperand(left1));
5988 __ mov(out2, ShifterOperand(left2));
5989
5926 __ Bind(&done); 5990 __ Bind(&done);
5927 if (FLAG_throw_on_javascript_int_overflow) { 5991 if (FLAG_throw_on_javascript_int_overflow) {
5928 Register tmp1 = locs()->in(1).reg(); 5992 EmitJavascriptIntOverflowCheck(compiler, deopt, out1, out2);
5929 Register tmp2 = locs()->temp(1).reg();
5930 EmitJavascriptIntOverflowCheck(compiler, deopt, out, tmp1, tmp2);
5931 } 5993 }
5932 } 5994 }
5933 5995
5934 5996
5935 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(bool opt) const { 5997 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(bool opt) const {
5936 const intptr_t kNumInputs = 1; 5998 const intptr_t kNumInputs = 1;
5937 const intptr_t kNumTemps = 5999 const intptr_t kNumTemps = 0;
5938 FLAG_throw_on_javascript_int_overflow ? 2 : 0;
5939 LocationSummary* summary = 6000 LocationSummary* summary =
5940 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 6001 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
5941 summary->set_in(0, Location::RequiresFpuRegister()); 6002 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
5942 summary->set_out(0, Location::RequiresFpuRegister()); 6003 Location::RequiresRegister()));
5943 if (FLAG_throw_on_javascript_int_overflow) { 6004 summary->set_out(0, Location::Pair(Location::RequiresRegister(),
5944 summary->set_temp(0, Location::RequiresRegister()); 6005 Location::RequiresRegister()));
5945 summary->set_temp(1, Location::RequiresRegister());
5946 }
5947 return summary; 6006 return summary;
5948 } 6007 }
5949 6008
5950 6009
5951 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 6010 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5952 ASSERT(op_kind() == Token::kBIT_NOT); 6011 ASSERT(op_kind() == Token::kBIT_NOT);
5953 QRegister value = locs()->in(0).fpu_reg(); 6012
5954 QRegister out = locs()->out(0).fpu_reg(); 6013 PairLocation* left_pair = locs()->in(0).AsPairLocation();
6014 Register left1 = left_pair->At(0).reg();
6015 Register left2 = left_pair->At(1).reg();
6016
6017 PairLocation* out_pair = locs()->out(0).AsPairLocation();
6018 Register out1 = out_pair->At(0).reg();
6019 Register out2 = out_pair->At(1).reg();
6020
5955 Label* deopt = NULL; 6021 Label* deopt = NULL;
6022
5956 if (FLAG_throw_on_javascript_int_overflow) { 6023 if (FLAG_throw_on_javascript_int_overflow) {
5957 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp); 6024 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp);
5958 } 6025 }
5959 __ vmvnq(out, value); 6026 __ mvn(out1, ShifterOperand(left1));
6027 __ mvn(out2, ShifterOperand(left2));
5960 if (FLAG_throw_on_javascript_int_overflow) { 6028 if (FLAG_throw_on_javascript_int_overflow) {
5961 Register tmp1 = locs()->temp(0).reg(); 6029 EmitJavascriptIntOverflowCheck(compiler, deopt, out1, out2);
5962 Register tmp2 = locs()->temp(1).reg();
5963 EmitJavascriptIntOverflowCheck(compiler, deopt, out, tmp1, tmp2);
5964 } 6030 }
5965 } 6031 }
5966 6032
5967 6033
5968 LocationSummary* ThrowInstr::MakeLocationSummary(bool opt) const { 6034 LocationSummary* ThrowInstr::MakeLocationSummary(bool opt) const {
5969 return new LocationSummary(0, 0, LocationSummary::kCall); 6035 return new LocationSummary(0, 0, LocationSummary::kCall);
5970 } 6036 }
5971 6037
5972 6038
5973 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 6039 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
6163 compiler->GenerateCall(token_pos(), 6229 compiler->GenerateCall(token_pos(),
6164 &label, 6230 &label,
6165 PcDescriptors::kOther, 6231 PcDescriptors::kOther,
6166 locs()); 6232 locs());
6167 __ Drop(ArgumentCount()); // Discard arguments. 6233 __ Drop(ArgumentCount()); // Discard arguments.
6168 } 6234 }
6169 6235
6170 } // namespace dart 6236 } // namespace dart
6171 6237
6172 #endif // defined TARGET_ARCH_ARM 6238 #endif // defined TARGET_ARCH_ARM
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698