OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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(¬_smi); | 5782 __ b(¬_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(¬_smi); | 5787 __ b(¬_smi); |
5757 | 5788 |
5758 __ Bind(&maybe_neg_smi); | 5789 __ Bind(&maybe_neg_smi); |
5759 __ CompareImmediate(lo, 0); | 5790 __ CompareImmediate(value1, 0); |
5760 __ b(¬_smi, GE); | 5791 __ b(¬_smi, GE); |
5761 __ CompareImmediate(lo, kSmiMin); | 5792 __ CompareImmediate(value1, kSmiMin); |
5762 __ b(¬_smi, LT); | 5793 __ b(¬_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(¬_smi); | 5802 __ Bind(¬_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 Loading... | |
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 |
OLD | NEW |