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_MIPS. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS. |
6 #if defined(TARGET_ARCH_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
7 | 7 |
8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
9 | 9 |
10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
(...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
432 case Token::kGTE: return GE; | 432 case Token::kGTE: return GE; |
433 default: | 433 default: |
434 UNREACHABLE(); | 434 UNREACHABLE(); |
435 return VS; | 435 return VS; |
436 } | 436 } |
437 } | 437 } |
438 | 438 |
439 | 439 |
440 // Branches on condition c assuming comparison results in CMPRES1 and CMPRES2. | 440 // Branches on condition c assuming comparison results in CMPRES1 and CMPRES2. |
441 static void EmitBranchAfterCompare( | 441 static void EmitBranchAfterCompare( |
442 FlowGraphCompiler* compiler, Condition c, Label* is_true) { | 442 FlowGraphCompiler* compiler, Condition condition, Label* is_true) { |
443 switch (c) { | 443 switch (condition) { |
444 case EQ: __ beq(CMPRES1, CMPRES2, is_true); break; | 444 case EQ: __ beq(CMPRES1, CMPRES2, is_true); break; |
445 case NE: __ bne(CMPRES1, CMPRES2, is_true); break; | 445 case NE: __ bne(CMPRES1, CMPRES2, is_true); break; |
446 case GT: __ bne(CMPRES2, ZR, is_true); break; | 446 case GT: __ bne(CMPRES2, ZR, is_true); break; |
447 case GE: __ beq(CMPRES1, ZR, is_true); break; | 447 case GE: __ beq(CMPRES1, ZR, is_true); break; |
448 case LT: __ bne(CMPRES1, ZR, is_true); break; | 448 case LT: __ bne(CMPRES1, ZR, is_true); break; |
449 case LE: __ beq(CMPRES2, ZR, is_true); break; | 449 case LE: __ beq(CMPRES2, ZR, is_true); break; |
450 default: | 450 default: |
451 UNREACHABLE(); | 451 UNREACHABLE(); |
452 break; | 452 break; |
453 } | 453 } |
454 } | 454 } |
455 | 455 |
456 | 456 |
457 static Condition FlipCondition(Condition condition) { | 457 static Condition FlipCondition(Condition condition) { |
458 switch (condition) { | 458 switch (condition) { |
459 case EQ: return EQ; | 459 case EQ: return EQ; |
460 case NE: return NE; | 460 case NE: return NE; |
461 case LT: return GT; | 461 case LT: return GT; |
462 case LE: return GE; | 462 case LE: return GE; |
463 case GT: return LT; | 463 case GT: return LT; |
464 case GE: return LE; | 464 case GE: return LE; |
465 default: | 465 default: |
466 UNREACHABLE(); | 466 UNREACHABLE(); |
467 return EQ; | 467 return EQ; |
468 } | 468 } |
469 } | 469 } |
470 | 470 |
471 | 471 |
472 // The comparison result is in CMPRES1. | 472 // The comparison result is in CMPRES1/CMPRES2. |
473 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, | 473 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, |
474 TargetEntryInstr* true_successor, | 474 Condition true_condition, |
475 TargetEntryInstr* false_successor, | 475 BranchLabels labels) { |
476 Condition true_condition) { | |
477 __ TraceSimMsg("ControlInstruction::EmitBranchOnCondition"); | 476 __ TraceSimMsg("ControlInstruction::EmitBranchOnCondition"); |
478 if (compiler->CanFallThroughTo(false_successor)) { | 477 if (labels.fall_through == labels.false_label) { |
479 // If the next block is the false successor, fall through to it. | 478 // If the next block is the false successor, fall through to it. |
480 Label* label = compiler->GetJumpLabel(true_successor); | 479 EmitBranchAfterCompare(compiler, true_condition, labels.true_label); |
481 EmitBranchAfterCompare(compiler, true_condition, label); | |
482 } else { | 480 } else { |
483 // If the next block is not the false successor, branch to it. | 481 // If the next block is not the false successor, branch to it. |
484 Condition false_condition = NegateCondition(true_condition); | 482 Condition false_condition = NegateCondition(true_condition); |
485 Label* label = compiler->GetJumpLabel(false_successor); | 483 EmitBranchAfterCompare(compiler, false_condition, labels.false_label); |
486 EmitBranchAfterCompare(compiler, false_condition, label); | |
487 // Fall through or jump to the true successor. | 484 // Fall through or jump to the true successor. |
488 if (!compiler->CanFallThroughTo(true_successor)) { | 485 if (labels.fall_through != labels.true_label) { |
489 __ b(compiler->GetJumpLabel(true_successor)); | 486 __ b(labels.true_label); |
490 } | 487 } |
491 } | 488 } |
492 } | 489 } |
493 | 490 |
494 | 491 |
495 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, | 492 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, |
496 const LocationSummary& locs, | 493 const LocationSummary& locs, |
497 Token::Kind kind, | 494 Token::Kind kind, |
498 BranchInstr* branch) { | 495 BranchLabels labels) { |
499 __ TraceSimMsg("EmitSmiComparisonOp"); | 496 __ TraceSimMsg("EmitSmiComparisonOp"); |
500 __ Comment("EmitSmiComparisonOp"); | 497 __ Comment("EmitSmiComparisonOp"); |
501 Location left = locs.in(0); | 498 Location left = locs.in(0); |
502 Location right = locs.in(1); | 499 Location right = locs.in(1); |
503 ASSERT(!left.IsConstant() || !right.IsConstant()); | 500 ASSERT(!left.IsConstant() || !right.IsConstant()); |
504 | 501 |
505 Condition true_condition = TokenKindToSmiCondition(kind); | 502 Condition true_condition = TokenKindToSmiCondition(kind); |
506 | 503 |
507 if (left.IsConstant()) { | 504 if (left.IsConstant()) { |
508 __ CompareObject(CMPRES1, CMPRES2, right.reg(), left.constant()); | 505 __ CompareObject(CMPRES1, CMPRES2, right.reg(), left.constant()); |
509 true_condition = FlipCondition(true_condition); | 506 true_condition = FlipCondition(true_condition); |
510 } else if (right.IsConstant()) { | 507 } else if (right.IsConstant()) { |
511 __ CompareObject(CMPRES1, CMPRES2, left.reg(), right.constant()); | 508 __ CompareObject(CMPRES1, CMPRES2, left.reg(), right.constant()); |
512 } else { | 509 } else { |
513 __ slt(CMPRES1, left.reg(), right.reg()); | 510 __ slt(CMPRES1, left.reg(), right.reg()); |
514 __ slt(CMPRES2, right.reg(), left.reg()); | 511 __ slt(CMPRES2, right.reg(), left.reg()); |
515 } | 512 } |
516 | 513 EmitBranchOnCondition(compiler, true_condition, labels); |
517 if (branch != NULL) { | |
518 EmitBranchOnCondition(compiler, | |
519 branch->true_successor(), | |
520 branch->false_successor(), | |
521 true_condition); | |
522 } else { | |
523 Register result = locs.out().reg(); | |
524 Label done, is_true; | |
525 EmitBranchAfterCompare(compiler, true_condition, &is_true); | |
526 __ LoadObject(result, Bool::False()); | |
527 __ b(&done); | |
528 __ Bind(&is_true); | |
529 __ LoadObject(result, Bool::True()); | |
530 __ Bind(&done); | |
531 } | |
532 } | |
533 | |
534 | |
535 static void EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, | |
536 const LocationSummary& locs, | |
537 Token::Kind kind, | |
538 BranchInstr* branch) { | |
539 UNIMPLEMENTED(); | |
540 } | |
541 | |
542 | |
543 static void EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, | |
544 const LocationSummary& locs, | |
545 Token::Kind kind, | |
546 BranchInstr* branch) { | |
547 UNIMPLEMENTED(); | |
548 } | 514 } |
549 | 515 |
550 | 516 |
551 static Condition TokenKindToDoubleCondition(Token::Kind kind) { | 517 static Condition TokenKindToDoubleCondition(Token::Kind kind) { |
552 switch (kind) { | 518 switch (kind) { |
553 case Token::kEQ: return EQ; | 519 case Token::kEQ: return EQ; |
554 case Token::kNE: return NE; | 520 case Token::kNE: return NE; |
555 case Token::kLT: return LT; | 521 case Token::kLT: return LT; |
556 case Token::kGT: return GT; | 522 case Token::kGT: return GT; |
557 case Token::kLTE: return LE; | 523 case Token::kLTE: return LE; |
558 case Token::kGTE: return GE; | 524 case Token::kGTE: return GE; |
559 default: | 525 default: |
560 UNREACHABLE(); | 526 UNREACHABLE(); |
561 return VS; | 527 return VS; |
562 } | 528 } |
563 } | 529 } |
564 | 530 |
565 | 531 |
566 static void EmitDoubleCompareBranch(FlowGraphCompiler* compiler, | 532 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
567 Condition true_condition, | 533 const LocationSummary& locs, |
568 FpuRegister left, | 534 Token::Kind kind, |
569 FpuRegister right, | 535 BranchLabels labels) { |
570 BranchInstr* branch) { | 536 DRegister left = locs.in(0).fpu_reg(); |
571 ASSERT(branch != NULL); | 537 DRegister right = locs.in(1).fpu_reg(); |
572 __ Comment("DoubleCompareBranch"); | 538 |
| 539 __ Comment("DoubleComparisonOp(left=%d, right=%d)", left, right); |
| 540 |
| 541 Condition true_condition = TokenKindToDoubleCondition(kind); |
573 __ cund(left, right); | 542 __ cund(left, right); |
574 BlockEntryInstr* nan_result = (true_condition == NE) ? | 543 Label* nan_label = (true_condition == NE) |
575 branch->true_successor() : branch->false_successor(); | 544 ? labels.true_label : labels.false_label; |
576 __ bc1t(compiler->GetJumpLabel(nan_result)); | 545 __ bc1t(nan_label); |
577 | 546 |
578 switch (true_condition) { | 547 switch (true_condition) { |
579 case EQ: __ ceqd(left, right); break; | 548 case EQ: __ ceqd(left, right); break; |
580 case NE: __ ceqd(left, right); break; | 549 case NE: __ ceqd(left, right); break; |
581 case LT: __ coltd(left, right); break; | 550 case LT: __ coltd(left, right); break; |
582 case LE: __ coled(left, right); break; | 551 case LE: __ coled(left, right); break; |
583 case GT: __ coltd(right, left); break; | 552 case GT: __ coltd(right, left); break; |
584 case GE: __ coled(right, left); break; | 553 case GE: __ coled(right, left); break; |
585 default: { | 554 default: { |
586 // Should only passing the above conditions to this function. | 555 // Should only passing the above conditions to this function. |
587 UNREACHABLE(); | 556 UNREACHABLE(); |
588 break; | 557 break; |
589 } | 558 } |
590 } | 559 } |
591 | 560 |
592 __ LoadImmediate(TMP, 1); | 561 __ LoadImmediate(TMP, 1); |
593 if (true_condition == NE) { | 562 if (true_condition == NE) { |
594 __ movf(CMPRES1, ZR); | 563 __ movf(CMPRES1, ZR); |
595 __ movt(CMPRES1, TMP); | 564 __ movt(CMPRES1, TMP); |
596 } else { | 565 } else { |
597 __ movf(CMPRES1, TMP); | 566 __ movf(CMPRES1, TMP); |
598 __ movt(CMPRES1, ZR); | 567 __ movt(CMPRES1, ZR); |
599 } | 568 } |
600 __ mov(CMPRES2, ZR); | 569 __ mov(CMPRES2, ZR); |
601 | 570 |
602 // EmitBranchOnCondition expects ordering to be described by CMPRES1, CMPRES2. | 571 // EmitBranchOnCondition expects ordering to be described by CMPRES1, CMPRES2. |
603 EmitBranchOnCondition(compiler, | 572 EmitBranchOnCondition(compiler, EQ, labels); |
604 branch->true_successor(), | |
605 branch->false_successor(), | |
606 EQ); | |
607 } | |
608 | |
609 | |
610 static void EmitDoubleCompareBool(FlowGraphCompiler* compiler, | |
611 Condition true_condition, | |
612 FpuRegister left, | |
613 FpuRegister right, | |
614 Register result) { | |
615 Label done, is_true; | |
616 Label* nan_label = (true_condition == NE) ? &is_true : &done; | |
617 __ Comment("DoubleCompareBool"); | |
618 __ LoadObject(result, Bool::False()); | |
619 __ cund(left, right); | |
620 __ bc1t(nan_label); | |
621 | |
622 switch (true_condition) { | |
623 case EQ: __ ceqd(left, right); break; | |
624 case NE: __ ceqd(left, right); break; | |
625 case LT: __ coltd(left, right); break; | |
626 case LE: __ coled(left, right); break; | |
627 case GT: __ coltd(right, left); break; | |
628 case GE: __ coled(right, left); break; | |
629 default: { | |
630 // Should only passing the above conditions to this function. | |
631 UNREACHABLE(); | |
632 break; | |
633 } | |
634 } | |
635 | |
636 if (true_condition == NE) { | |
637 __ bc1t(&done); // False is already in result. | |
638 } else { | |
639 __ bc1f(&done); | |
640 } | |
641 __ Bind(&is_true); | |
642 __ LoadObject(result, Bool::True()); | |
643 __ Bind(&done); | |
644 } | |
645 | |
646 | |
647 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, | |
648 const LocationSummary& locs, | |
649 Token::Kind kind, | |
650 BranchInstr* branch) { | |
651 DRegister left = locs.in(0).fpu_reg(); | |
652 DRegister right = locs.in(1).fpu_reg(); | |
653 | |
654 __ Comment("DoubleComparisonOp(left=%d, right=%d)", left, right); | |
655 | |
656 Condition true_condition = TokenKindToDoubleCondition(kind); | |
657 if (branch != NULL) { | |
658 EmitDoubleCompareBranch(compiler, true_condition, left, right, branch); | |
659 } else { | |
660 EmitDoubleCompareBool(compiler, true_condition, | |
661 left, right, locs.out().reg()); | |
662 } | |
663 } | 573 } |
664 | 574 |
665 | 575 |
666 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 576 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
667 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 577 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
668 BranchInstr* kNoBranch = NULL; | |
669 __ Comment("EqualityCompareInstr"); | 578 __ Comment("EqualityCompareInstr"); |
| 579 |
| 580 Label is_true, is_false; |
| 581 BranchLabels labels = { &is_true, &is_false, &is_false }; |
| 582 |
670 if (operation_cid() == kSmiCid) { | 583 if (operation_cid() == kSmiCid) { |
671 EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch); | 584 EmitSmiComparisonOp(compiler, *locs(), kind(), labels); |
672 return; | 585 } else { |
| 586 ASSERT(operation_cid() == kDoubleCid); |
| 587 EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
673 } | 588 } |
674 if (operation_cid() == kMintCid) { | 589 Register result = locs()->out().reg(); |
675 EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), kNoBranch); | 590 Label done; |
676 return; | 591 __ Bind(&is_false); |
677 } | 592 __ LoadObject(result, Bool::False()); |
678 if (operation_cid() == kDoubleCid) { | 593 __ b(&done); |
679 EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch); | 594 __ Bind(&is_true); |
680 return; | 595 __ LoadObject(result, Bool::True()); |
681 } | 596 __ Bind(&done); |
682 UNREACHABLE(); | |
683 } | 597 } |
684 | 598 |
685 | 599 |
686 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 600 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
687 BranchInstr* branch) { | 601 BranchInstr* branch) { |
688 __ TraceSimMsg("EqualityCompareInstr"); | 602 __ TraceSimMsg("EqualityCompareInstr"); |
689 __ Comment("EqualityCompareInstr:BranchCode"); | 603 __ Comment("EqualityCompareInstr:BranchCode"); |
690 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 604 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
| 605 |
| 606 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 607 |
691 if (operation_cid() == kSmiCid) { | 608 if (operation_cid() == kSmiCid) { |
692 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); | 609 EmitSmiComparisonOp(compiler, *locs(), kind(), labels); |
693 return; | 610 } else { |
| 611 ASSERT(operation_cid() == kDoubleCid); |
| 612 EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
694 } | 613 } |
695 if (operation_cid() == kMintCid) { | |
696 EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), branch); | |
697 return; | |
698 } | |
699 if (operation_cid() == kDoubleCid) { | |
700 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); | |
701 return; | |
702 } | |
703 UNREACHABLE(); | |
704 } | 614 } |
705 | 615 |
706 | 616 |
707 LocationSummary* TestSmiInstr::MakeLocationSummary() const { | 617 LocationSummary* TestSmiInstr::MakeLocationSummary() const { |
708 const intptr_t kNumInputs = 2; | 618 const intptr_t kNumInputs = 2; |
709 const intptr_t kNumTemps = 0; | 619 const intptr_t kNumTemps = 0; |
710 LocationSummary* locs = | 620 LocationSummary* locs = |
711 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 621 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
712 locs->set_in(0, Location::RequiresRegister()); | 622 locs->set_in(0, Location::RequiresRegister()); |
713 // Only one input can be a constant operand. The case of two constant | 623 // Only one input can be a constant operand. The case of two constant |
714 // operands should be handled by constant propagation. | 624 // operands should be handled by constant propagation. |
715 locs->set_in(1, Location::RegisterOrConstant(right())); | 625 locs->set_in(1, Location::RegisterOrConstant(right())); |
716 return locs; | 626 return locs; |
717 } | 627 } |
718 | 628 |
719 | 629 |
720 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 630 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
721 // Never emitted outside of the BranchInstr. | 631 // Never emitted outside of the BranchInstr. |
722 UNREACHABLE(); | 632 UNREACHABLE(); |
723 } | 633 } |
724 | 634 |
725 | 635 |
726 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 636 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
727 BranchInstr* branch) { | 637 BranchInstr* branch) { |
728 Condition branch_condition = (kind() == Token::kNE) ? NE : EQ; | 638 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 639 |
| 640 Condition true_condition = (kind() == Token::kNE) ? NE : EQ; |
729 Register left = locs()->in(0).reg(); | 641 Register left = locs()->in(0).reg(); |
730 Location right = locs()->in(1); | 642 Location right = locs()->in(1); |
731 if (right.IsConstant()) { | 643 if (right.IsConstant()) { |
732 ASSERT(right.constant().IsSmi()); | 644 ASSERT(right.constant().IsSmi()); |
733 const int32_t imm = | 645 const int32_t imm = |
734 reinterpret_cast<int32_t>(right.constant().raw()); | 646 reinterpret_cast<int32_t>(right.constant().raw()); |
735 __ AndImmediate(CMPRES1, left, imm); | 647 __ AndImmediate(CMPRES1, left, imm); |
736 } else { | 648 } else { |
737 __ and_(CMPRES1, left, right.reg()); | 649 __ and_(CMPRES1, left, right.reg()); |
738 } | 650 } |
739 __ mov(CMPRES2, ZR); | 651 __ mov(CMPRES2, ZR); |
740 EmitBranchOnCondition(compiler, | 652 EmitBranchOnCondition(compiler, true_condition, labels); |
741 branch->true_successor(), | |
742 branch->false_successor(), | |
743 branch_condition); | |
744 } | 653 } |
745 | 654 |
746 | 655 |
747 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { | 656 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { |
748 const intptr_t kNumInputs = 2; | 657 const intptr_t kNumInputs = 2; |
749 const intptr_t kNumTemps = 0; | 658 const intptr_t kNumTemps = 0; |
750 if (operation_cid() == kMintCid) { | 659 if (operation_cid() == kMintCid) { |
751 const intptr_t kNumTemps = 2; | 660 const intptr_t kNumTemps = 2; |
752 LocationSummary* locs = | 661 LocationSummary* locs = |
753 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 662 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
(...skipping 21 matching lines...) Expand all Loading... |
775 summary->set_in(1, summary->in(0).IsConstant() | 684 summary->set_in(1, summary->in(0).IsConstant() |
776 ? Location::RequiresRegister() | 685 ? Location::RequiresRegister() |
777 : Location::RegisterOrConstant(right())); | 686 : Location::RegisterOrConstant(right())); |
778 summary->set_out(Location::RequiresRegister()); | 687 summary->set_out(Location::RequiresRegister()); |
779 return summary; | 688 return summary; |
780 } | 689 } |
781 | 690 |
782 | 691 |
783 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 692 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
784 __ TraceSimMsg("RelationalOpInstr"); | 693 __ TraceSimMsg("RelationalOpInstr"); |
| 694 |
| 695 Label is_true, is_false; |
| 696 BranchLabels labels = { &is_true, &is_false, &is_false }; |
| 697 |
785 if (operation_cid() == kSmiCid) { | 698 if (operation_cid() == kSmiCid) { |
786 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL); | 699 EmitSmiComparisonOp(compiler, *locs(), kind(), labels); |
787 return; | 700 } else { |
| 701 ASSERT(operation_cid() == kDoubleCid); |
| 702 EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
788 } | 703 } |
789 if (operation_cid() == kMintCid) { | 704 Register result = locs()->out().reg(); |
790 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), NULL); | 705 Label done; |
791 return; | 706 __ Bind(&is_false); |
792 } | 707 __ LoadObject(result, Bool::False()); |
793 ASSERT(operation_cid() == kDoubleCid); | 708 __ b(&done); |
794 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL); | 709 __ Bind(&is_true); |
795 return; | 710 __ LoadObject(result, Bool::True()); |
| 711 __ Bind(&done); |
796 } | 712 } |
797 | 713 |
798 | 714 |
799 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 715 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
800 BranchInstr* branch) { | 716 BranchInstr* branch) { |
801 __ TraceSimMsg("RelationalOpInstr"); | 717 __ TraceSimMsg("RelationalOpInstr"); |
| 718 |
| 719 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 720 |
802 if (operation_cid() == kSmiCid) { | 721 if (operation_cid() == kSmiCid) { |
803 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); | 722 EmitSmiComparisonOp(compiler, *locs(), kind(), labels); |
804 return; | 723 } else { |
| 724 ASSERT(operation_cid() == kDoubleCid); |
| 725 EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
805 } | 726 } |
806 if (operation_cid() == kMintCid) { | |
807 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), branch); | |
808 return; | |
809 } | |
810 ASSERT(operation_cid() == kDoubleCid); | |
811 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); | |
812 } | 727 } |
813 | 728 |
814 | 729 |
815 LocationSummary* NativeCallInstr::MakeLocationSummary() const { | 730 LocationSummary* NativeCallInstr::MakeLocationSummary() const { |
816 const intptr_t kNumInputs = 0; | 731 const intptr_t kNumInputs = 0; |
817 const intptr_t kNumTemps = 3; | 732 const intptr_t kNumTemps = 3; |
818 LocationSummary* locs = | 733 LocationSummary* locs = |
819 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 734 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
820 locs->set_temp(0, Location::RegisterLocation(A1)); | 735 locs->set_temp(0, Location::RegisterLocation(A1)); |
821 locs->set_temp(1, Location::RegisterLocation(A2)); | 736 locs->set_temp(1, Location::RegisterLocation(A2)); |
(...skipping 3018 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3840 // Only one of the inputs can be a constant. Choose register if the first one | 3755 // Only one of the inputs can be a constant. Choose register if the first one |
3841 // is a constant. | 3756 // is a constant. |
3842 locs->set_in(1, locs->in(0).IsConstant() | 3757 locs->set_in(1, locs->in(0).IsConstant() |
3843 ? Location::RequiresRegister() | 3758 ? Location::RequiresRegister() |
3844 : Location::RegisterOrConstant(right())); | 3759 : Location::RegisterOrConstant(right())); |
3845 locs->set_out(Location::RequiresRegister()); | 3760 locs->set_out(Location::RequiresRegister()); |
3846 return locs; | 3761 return locs; |
3847 } | 3762 } |
3848 | 3763 |
3849 | 3764 |
| 3765 static void EmitStrictComparison(FlowGraphCompiler* compiler, |
| 3766 StrictCompareInstr* compare, |
| 3767 BranchLabels labels) { |
| 3768 LocationSummary* locs = compare->locs(); |
| 3769 bool needs_number_check = compare->needs_number_check(); |
| 3770 intptr_t token_pos = compare->token_pos(); |
| 3771 Token::Kind kind = compare->kind(); |
| 3772 Location left = locs->in(0); |
| 3773 Location right = locs->in(1); |
| 3774 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 3775 if (left.IsConstant()) { |
| 3776 compiler->EmitEqualityRegConstCompare(right.reg(), |
| 3777 left.constant(), |
| 3778 needs_number_check, |
| 3779 token_pos); |
| 3780 } else if (right.IsConstant()) { |
| 3781 compiler->EmitEqualityRegConstCompare(left.reg(), |
| 3782 right.constant(), |
| 3783 needs_number_check, |
| 3784 token_pos); |
| 3785 } else { |
| 3786 compiler->EmitEqualityRegRegCompare(left.reg(), |
| 3787 right.reg(), |
| 3788 needs_number_check, |
| 3789 token_pos); |
| 3790 } |
| 3791 Condition true_condition = (kind == Token::kEQ_STRICT) ? EQ : NE; |
| 3792 EmitBranchOnCondition(compiler, true_condition, labels); |
| 3793 } |
| 3794 |
3850 // Special code for numbers (compare values instead of references.) | 3795 // Special code for numbers (compare values instead of references.) |
3851 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3796 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3852 __ TraceSimMsg("StrictCompareInstr"); | 3797 __ TraceSimMsg("StrictCompareInstr"); |
3853 __ Comment("StrictCompareInstr"); | 3798 __ Comment("StrictCompareInstr"); |
3854 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 3799 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
3855 Location left = locs()->in(0); | 3800 |
3856 Location right = locs()->in(1); | 3801 Label is_true, is_false; |
3857 ASSERT(!left.IsConstant() || !right.IsConstant()); | 3802 BranchLabels labels = { &is_true, &is_false, &is_false }; |
3858 if (left.IsConstant()) { | 3803 |
3859 compiler->EmitEqualityRegConstCompare(right.reg(), | 3804 EmitStrictComparison(compiler, this, labels); |
3860 left.constant(), | |
3861 needs_number_check(), | |
3862 token_pos()); | |
3863 } else if (right.IsConstant()) { | |
3864 compiler->EmitEqualityRegConstCompare(left.reg(), | |
3865 right.constant(), | |
3866 needs_number_check(), | |
3867 token_pos()); | |
3868 } else { | |
3869 compiler->EmitEqualityRegRegCompare(left.reg(), | |
3870 right.reg(), | |
3871 needs_number_check(), | |
3872 token_pos()); | |
3873 } | |
3874 | 3805 |
3875 Register result = locs()->out().reg(); | 3806 Register result = locs()->out().reg(); |
3876 Label load_true, done; | 3807 Label done; |
3877 if (kind() == Token::kEQ_STRICT) { | 3808 __ Bind(&is_false); |
3878 __ beq(CMPRES1, CMPRES2, &load_true); | |
3879 } else { | |
3880 ASSERT(kind() == Token::kNE_STRICT); | |
3881 __ bne(CMPRES1, CMPRES2, &load_true); | |
3882 } | |
3883 __ LoadObject(result, Bool::False()); | 3809 __ LoadObject(result, Bool::False()); |
3884 __ b(&done); | 3810 __ b(&done); |
3885 __ Bind(&load_true); | 3811 __ Bind(&is_true); |
3886 __ LoadObject(result, Bool::True()); | 3812 __ LoadObject(result, Bool::True()); |
3887 __ Bind(&done); | 3813 __ Bind(&done); |
3888 } | 3814 } |
3889 | 3815 |
3890 | 3816 |
3891 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 3817 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
3892 BranchInstr* branch) { | 3818 BranchInstr* branch) { |
3893 __ TraceSimMsg("StrictCompareInstr::EmitBranchCode"); | 3819 __ TraceSimMsg("StrictCompareInstr::EmitBranchCode"); |
3894 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 3820 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
3895 Location left = locs()->in(0); | |
3896 Location right = locs()->in(1); | |
3897 ASSERT(!left.IsConstant() || !right.IsConstant()); | |
3898 if (left.IsConstant()) { | |
3899 compiler->EmitEqualityRegConstCompare(right.reg(), | |
3900 left.constant(), | |
3901 needs_number_check(), | |
3902 token_pos()); | |
3903 } else if (right.IsConstant()) { | |
3904 compiler->EmitEqualityRegConstCompare(left.reg(), | |
3905 right.constant(), | |
3906 needs_number_check(), | |
3907 token_pos()); | |
3908 } else { | |
3909 compiler->EmitEqualityRegRegCompare(left.reg(), | |
3910 right.reg(), | |
3911 needs_number_check(), | |
3912 token_pos()); | |
3913 } | |
3914 | 3821 |
3915 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQ : NE; | 3822 BranchLabels labels = compiler->CreateBranchLabels(branch); |
3916 EmitBranchOnCondition(compiler, | 3823 |
3917 branch->true_successor(), | 3824 EmitStrictComparison(compiler, this, labels); |
3918 branch->false_successor(), | |
3919 true_condition); | |
3920 } | 3825 } |
3921 | 3826 |
3922 | 3827 |
3923 LocationSummary* BooleanNegateInstr::MakeLocationSummary() const { | 3828 LocationSummary* BooleanNegateInstr::MakeLocationSummary() const { |
3924 return LocationSummary::Make(1, | 3829 return LocationSummary::Make(1, |
3925 Location::RequiresRegister(), | 3830 Location::RequiresRegister(), |
3926 LocationSummary::kNoCall); | 3831 LocationSummary::kNoCall); |
3927 } | 3832 } |
3928 | 3833 |
3929 | 3834 |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3997 compiler->GenerateCall(token_pos(), | 3902 compiler->GenerateCall(token_pos(), |
3998 &label, | 3903 &label, |
3999 PcDescriptors::kOther, | 3904 PcDescriptors::kOther, |
4000 locs()); | 3905 locs()); |
4001 __ Drop(2); // Discard type arguments and receiver. | 3906 __ Drop(2); // Discard type arguments and receiver. |
4002 } | 3907 } |
4003 | 3908 |
4004 } // namespace dart | 3909 } // namespace dart |
4005 | 3910 |
4006 #endif // defined TARGET_ARCH_MIPS | 3911 #endif // defined TARGET_ARCH_MIPS |
OLD | NEW |