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

Side by Side Diff: src/mips/assembler-mips.cc

Issue 1396133002: MIPS: r6 compact branch optimization. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebased, gcc build fixed, ra alignment failure fixed. Created 5 years, 2 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
OLDNEW
1 // Copyright (c) 1994-2006 Sun Microsystems Inc. 1 // Copyright (c) 1994-2006 Sun Microsystems Inc.
2 // All Rights Reserved. 2 // All Rights Reserved.
3 // 3 //
4 // Redistribution and use in source and binary forms, with or without 4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are 5 // modification, are permitted provided that the following conditions are
6 // met: 6 // met:
7 // 7 //
8 // - Redistributions of source code must retain the above copyright notice, 8 // - Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer. 9 // this list of conditions and the following disclaimer.
10 // 10 //
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 desc->buffer = buffer_; 290 desc->buffer = buffer_;
291 desc->buffer_size = buffer_size_; 291 desc->buffer_size = buffer_size_;
292 desc->instr_size = pc_offset(); 292 desc->instr_size = pc_offset();
293 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); 293 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
294 desc->origin = this; 294 desc->origin = this;
295 } 295 }
296 296
297 297
298 void Assembler::Align(int m) { 298 void Assembler::Align(int m) {
299 DCHECK(m >= 4 && base::bits::IsPowerOfTwo32(m)); 299 DCHECK(m >= 4 && base::bits::IsPowerOfTwo32(m));
300 if (IsPrevInstrCompactBranch()) {
301 nop();
302 ClearCompactBranchState();
303 }
300 while ((pc_offset() & (m - 1)) != 0) { 304 while ((pc_offset() & (m - 1)) != 0) {
301 nop(); 305 nop();
302 } 306 }
303 } 307 }
304 308
305 309
306 void Assembler::CodeTargetAlign() { 310 void Assembler::CodeTargetAlign() {
307 // No advantage to aligning branch/call targets to more than 311 // No advantage to aligning branch/call targets to more than
308 // single instruction, that I am aware of. 312 // single instruction, that I am aware of.
309 Align(4); 313 Align(4);
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
446 const int kEndOfChain = -4; 450 const int kEndOfChain = -4;
447 // Determines the end of the Jump chain (a subset of the label link chain). 451 // Determines the end of the Jump chain (a subset of the label link chain).
448 const int kEndOfJumpChain = 0; 452 const int kEndOfJumpChain = 0;
449 453
450 454
451 bool Assembler::IsBranch(Instr instr) { 455 bool Assembler::IsBranch(Instr instr) {
452 uint32_t opcode = GetOpcodeField(instr); 456 uint32_t opcode = GetOpcodeField(instr);
453 uint32_t rt_field = GetRtField(instr); 457 uint32_t rt_field = GetRtField(instr);
454 uint32_t rs_field = GetRsField(instr); 458 uint32_t rs_field = GetRsField(instr);
455 // Checks if the instruction is a branch. 459 // Checks if the instruction is a branch.
456 return opcode == BEQ || 460 bool isBranch =
457 opcode == BNE || 461 opcode == BEQ || opcode == BNE || opcode == BLEZ || opcode == BGTZ ||
458 opcode == BLEZ || 462 opcode == BEQL || opcode == BNEL || opcode == BLEZL || opcode == BGTZL ||
459 opcode == BGTZ ||
460 opcode == BEQL ||
461 opcode == BNEL ||
462 opcode == BLEZL ||
463 opcode == BGTZL ||
464 (opcode == REGIMM && (rt_field == BLTZ || rt_field == BGEZ || 463 (opcode == REGIMM && (rt_field == BLTZ || rt_field == BGEZ ||
465 rt_field == BLTZAL || rt_field == BGEZAL)) || 464 rt_field == BLTZAL || rt_field == BGEZAL)) ||
466 (opcode == COP1 && rs_field == BC1) || // Coprocessor branch. 465 (opcode == COP1 && rs_field == BC1) || // Coprocessor branch.
467 (opcode == COP1 && rs_field == BC1EQZ) || 466 (opcode == COP1 && rs_field == BC1EQZ) ||
468 (opcode == COP1 && rs_field == BC1NEZ); 467 (opcode == COP1 && rs_field == BC1NEZ);
468 if (!isBranch && IsMipsArchVariant(kMips32r6)) {
469 // All the 3 variants of POP10 (BOVC, BEQC, BEQZALC) and
470 // POP30 (BNVC, BNEC, BNEZALC) are branch ops.
471 isBranch |= opcode == POP10 || opcode == POP30 || opcode == BC ||
472 opcode == BALC ||
473 (opcode == POP66 && rs_field != 0) || // BEQZC
474 (opcode == POP76 && rs_field != 0); // BNEZC
475 }
476 return isBranch;
469 } 477 }
470 478
471 479
480 bool Assembler::IsBc(Instr instr) {
481 uint32_t opcode = GetOpcodeField(instr);
482 // Checks if the instruction is a BC or BALC.
483 return opcode == BC || opcode == BALC;
484 }
485
486
487 bool Assembler::IsBzc(Instr instr) {
488 uint32_t opcode = GetOpcodeField(instr);
489 // Checks if the instruction is BEQZC or BNEZC.
490 return (opcode == POP66 && GetRsField(instr) != 0) ||
491 (opcode == POP76 && GetRsField(instr) != 0);
492 }
493
494
472 bool Assembler::IsEmittedConstant(Instr instr) { 495 bool Assembler::IsEmittedConstant(Instr instr) {
473 uint32_t label_constant = GetLabelConst(instr); 496 uint32_t label_constant = GetLabelConst(instr);
474 return label_constant == 0; // Emitted label const in reg-exp engine. 497 return label_constant == 0; // Emitted label const in reg-exp engine.
475 } 498 }
476 499
477 500
478 bool Assembler::IsBeq(Instr instr) { 501 bool Assembler::IsBeq(Instr instr) {
479 return GetOpcodeField(instr) == BEQ; 502 return GetOpcodeField(instr) == BEQ;
480 } 503 }
481 504
482 505
483 bool Assembler::IsBne(Instr instr) { 506 bool Assembler::IsBne(Instr instr) {
484 return GetOpcodeField(instr) == BNE; 507 return GetOpcodeField(instr) == BNE;
485 } 508 }
486 509
487 510
511 bool Assembler::IsBeqzc(Instr instr) {
512 uint32_t opcode = GetOpcodeField(instr);
513 return opcode == POP66 && GetRsField(instr) != 0;
514 }
515
516
517 bool Assembler::IsBnezc(Instr instr) {
518 uint32_t opcode = GetOpcodeField(instr);
519 return opcode == POP76 && GetRsField(instr) != 0;
520 }
521
522
523 bool Assembler::IsBeqc(Instr instr) {
524 uint32_t opcode = GetOpcodeField(instr);
525 uint32_t rs = GetRsField(instr);
526 uint32_t rt = GetRtField(instr);
527 return opcode == POP10 && rs != 0 && rs < rt; // && rt != 0
528 }
529
530
531 bool Assembler::IsBnec(Instr instr) {
532 uint32_t opcode = GetOpcodeField(instr);
533 uint32_t rs = GetRsField(instr);
534 uint32_t rt = GetRtField(instr);
535 return opcode == POP30 && rs != 0 && rs < rt; // && rt != 0
536 }
537
538
488 bool Assembler::IsJump(Instr instr) { 539 bool Assembler::IsJump(Instr instr) {
489 uint32_t opcode = GetOpcodeField(instr); 540 uint32_t opcode = GetOpcodeField(instr);
490 uint32_t rt_field = GetRtField(instr); 541 uint32_t rt_field = GetRtField(instr);
491 uint32_t rd_field = GetRdField(instr); 542 uint32_t rd_field = GetRdField(instr);
492 uint32_t function_field = GetFunctionField(instr); 543 uint32_t function_field = GetFunctionField(instr);
493 // Checks if the instruction is a jump. 544 // Checks if the instruction is a jump.
494 return opcode == J || opcode == JAL || 545 return opcode == J || opcode == JAL ||
495 (opcode == SPECIAL && rt_field == 0 && 546 (opcode == SPECIAL && rt_field == 0 &&
496 ((function_field == JALR) || (rd_field == 0 && (function_field == JR)))); 547 ((function_field == JALR) || (rd_field == 0 && (function_field == JR))));
497 } 548 }
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
563 } 614 }
564 615
565 616
566 int32_t Assembler::GetBranchOffset(Instr instr) { 617 int32_t Assembler::GetBranchOffset(Instr instr) {
567 DCHECK(IsBranch(instr)); 618 DCHECK(IsBranch(instr));
568 return (static_cast<int16_t>(instr & kImm16Mask)) << 2; 619 return (static_cast<int16_t>(instr & kImm16Mask)) << 2;
569 } 620 }
570 621
571 622
572 bool Assembler::IsLw(Instr instr) { 623 bool Assembler::IsLw(Instr instr) {
573 return ((instr & kOpcodeMask) == LW); 624 return (static_cast<uint32_t>(instr & kOpcodeMask) == LW);
574 } 625 }
575 626
576 627
577 int16_t Assembler::GetLwOffset(Instr instr) { 628 int16_t Assembler::GetLwOffset(Instr instr) {
578 DCHECK(IsLw(instr)); 629 DCHECK(IsLw(instr));
579 return ((instr & kImm16Mask)); 630 return ((instr & kImm16Mask));
580 } 631 }
581 632
582 633
583 Instr Assembler::SetLwOffset(Instr instr, int16_t offset) { 634 Instr Assembler::SetLwOffset(Instr instr, int16_t offset) {
584 DCHECK(IsLw(instr)); 635 DCHECK(IsLw(instr));
585 636
586 // We actually create a new lw instruction based on the original one. 637 // We actually create a new lw instruction based on the original one.
587 Instr temp_instr = LW | (instr & kRsFieldMask) | (instr & kRtFieldMask) 638 Instr temp_instr = LW | (instr & kRsFieldMask) | (instr & kRtFieldMask)
588 | (offset & kImm16Mask); 639 | (offset & kImm16Mask);
589 640
590 return temp_instr; 641 return temp_instr;
591 } 642 }
592 643
593 644
594 bool Assembler::IsSw(Instr instr) { 645 bool Assembler::IsSw(Instr instr) {
595 return ((instr & kOpcodeMask) == SW); 646 return (static_cast<uint32_t>(instr & kOpcodeMask) == SW);
596 } 647 }
597 648
598 649
599 Instr Assembler::SetSwOffset(Instr instr, int16_t offset) { 650 Instr Assembler::SetSwOffset(Instr instr, int16_t offset) {
600 DCHECK(IsSw(instr)); 651 DCHECK(IsSw(instr));
601 return ((instr & ~kImm16Mask) | (offset & kImm16Mask)); 652 return ((instr & ~kImm16Mask) | (offset & kImm16Mask));
602 } 653 }
603 654
604 655
605 bool Assembler::IsAddImmediate(Instr instr) { 656 bool Assembler::IsAddImmediate(Instr instr) {
606 return ((instr & kOpcodeMask) == ADDIU); 657 return ((instr & kOpcodeMask) == ADDIU);
607 } 658 }
608 659
609 660
610 Instr Assembler::SetAddImmediateOffset(Instr instr, int16_t offset) { 661 Instr Assembler::SetAddImmediateOffset(Instr instr, int16_t offset) {
611 DCHECK(IsAddImmediate(instr)); 662 DCHECK(IsAddImmediate(instr));
612 return ((instr & ~kImm16Mask) | (offset & kImm16Mask)); 663 return ((instr & ~kImm16Mask) | (offset & kImm16Mask));
613 } 664 }
614 665
615 666
616 bool Assembler::IsAndImmediate(Instr instr) { 667 bool Assembler::IsAndImmediate(Instr instr) {
617 return GetOpcodeField(instr) == ANDI; 668 return GetOpcodeField(instr) == ANDI;
618 } 669 }
619 670
620 671
672 static int32_t OffsetSizeInBits(Instr instr) {
673 if (IsMipsArchVariant(kMips32r6)) {
674 if (Assembler::IsBc(instr)) {
675 return 26;
ivica.bogosavljevic 2015/10/15 11:49:08 Use contstants instead of number
balazs.kilvady 2015/10/30 21:11:14 Done.
676 } else if (Assembler::IsBzc(instr)) {
677 return 21;
678 }
679 }
680 return 16;
681 }
682
683
684 static inline int32_t AddBranchOffset(int pos, Instr instr) {
685 int32_t bits = OffsetSizeInBits(instr);
686 const int32_t mask = (1 << bits) - 1;
687 bits = 32 - bits;
688
689 // Do NOT change this to <<2. We rely on arithmetic shifts here, assuming
690 // the compiler uses arithmetic shifts for signed integers.
691 int32_t imm = ((instr & mask) << bits) >> (bits - 2);
692
693 if (imm == kEndOfChain) {
694 // EndOfChain sentinel is returned directly, not relative to pc or pos.
695 return kEndOfChain;
696 } else {
697 return pos + Assembler::kBranchPCOffset + imm;
698 }
699 }
700
701
621 int Assembler::target_at(int pos, bool is_internal) { 702 int Assembler::target_at(int pos, bool is_internal) {
622 Instr instr = instr_at(pos); 703 Instr instr = instr_at(pos);
623 if (is_internal) { 704 if (is_internal) {
624 if (instr == 0) { 705 if (instr == 0) {
625 return kEndOfChain; 706 return kEndOfChain;
626 } else { 707 } else {
627 int32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos); 708 int32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos);
628 int delta = static_cast<int>(instr_address - instr); 709 int delta = static_cast<int>(instr_address - instr);
629 DCHECK(pos > delta); 710 DCHECK(pos > delta);
630 return pos - delta; 711 return pos - delta;
631 } 712 }
632 } 713 }
633 if ((instr & ~kImm16Mask) == 0) { 714 if ((instr & ~kImm16Mask) == 0) {
634 // Emitted label constant, not part of a branch. 715 // Emitted label constant, not part of a branch.
635 if (instr == 0) { 716 if (instr == 0) {
636 return kEndOfChain; 717 return kEndOfChain;
637 } else { 718 } else {
638 int32_t imm18 =((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14; 719 int32_t imm18 =((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14;
639 return (imm18 + pos); 720 return (imm18 + pos);
640 } 721 }
641 } 722 }
642 // Check we have a branch or jump instruction. 723 // Check we have a branch or jump instruction.
643 DCHECK(IsBranch(instr) || IsLui(instr)); 724 DCHECK(IsBranch(instr) || IsLui(instr));
644 // Do NOT change this to <<2. We rely on arithmetic shifts here, assuming
645 // the compiler uses arithmetic shifts for signed integers.
646 if (IsBranch(instr)) { 725 if (IsBranch(instr)) {
647 int32_t imm18 = ((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14; 726 return AddBranchOffset(pos, instr);
648 727 } else {
649 if (imm18 == kEndOfChain) {
650 // EndOfChain sentinel is returned directly, not relative to pc or pos.
651 return kEndOfChain;
652 } else {
653 return pos + kBranchPCOffset + imm18;
654 }
655 } else if (IsLui(instr)) {
656 Instr instr_lui = instr_at(pos + 0 * Assembler::kInstrSize); 728 Instr instr_lui = instr_at(pos + 0 * Assembler::kInstrSize);
657 Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize); 729 Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize);
658 DCHECK(IsOri(instr_ori)); 730 DCHECK(IsOri(instr_ori));
ivica.bogosavljevic 2015/10/15 11:49:08 Since isLui is not part of else if, then we should
balazs.kilvady 2015/10/30 21:11:14 That check is covered at line 724
659 int32_t imm = (instr_lui & static_cast<int32_t>(kImm16Mask)) << kLuiShift; 731 int32_t imm = (instr_lui & static_cast<int32_t>(kImm16Mask)) << kLuiShift;
660 imm |= (instr_ori & static_cast<int32_t>(kImm16Mask)); 732 imm |= (instr_ori & static_cast<int32_t>(kImm16Mask));
661 733
662 if (imm == kEndOfJumpChain) { 734 if (imm == kEndOfJumpChain) {
663 // EndOfChain sentinel is returned directly, not relative to pc or pos. 735 // EndOfChain sentinel is returned directly, not relative to pc or pos.
664 return kEndOfChain; 736 return kEndOfChain;
665 } else { 737 } else {
666 uint32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos); 738 uint32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos);
667 int32_t delta = instr_address - imm; 739 int32_t delta = instr_address - imm;
668 DCHECK(pos > delta); 740 DCHECK(pos > delta);
669 return pos - delta; 741 return pos - delta;
670 } 742 }
671 } else {
672 UNREACHABLE();
673 return 0;
674 } 743 }
744 return 0;
675 } 745 }
676 746
677 747
748 static inline Instr SetBranchOffset(int32_t pos, int32_t target_pos,
749 Instr instr) {
750 int32_t bits = OffsetSizeInBits(instr);
751 int32_t imm = target_pos - (pos + Assembler::kBranchPCOffset);
752 DCHECK((imm & 3) == 0);
753 imm >>= 2;
754
755 const int32_t mask = (1 << bits) - 1;
756 instr &= ~mask;
757 DCHECK(is_intn(imm, bits));
758
759 return instr | (imm & mask);
760 }
761
762
678 void Assembler::target_at_put(int32_t pos, int32_t target_pos, 763 void Assembler::target_at_put(int32_t pos, int32_t target_pos,
679 bool is_internal) { 764 bool is_internal) {
680 Instr instr = instr_at(pos); 765 Instr instr = instr_at(pos);
681 766
682 if (is_internal) { 767 if (is_internal) {
683 uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos; 768 uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos;
684 instr_at_put(pos, imm); 769 instr_at_put(pos, imm);
685 return; 770 return;
686 } 771 }
687 if ((instr & ~kImm16Mask) == 0) { 772 if ((instr & ~kImm16Mask) == 0) {
688 DCHECK(target_pos == kEndOfChain || target_pos >= 0); 773 DCHECK(target_pos == kEndOfChain || target_pos >= 0);
689 // Emitted label constant, not part of a branch. 774 // Emitted label constant, not part of a branch.
690 // Make label relative to Code* of generated Code object. 775 // Make label relative to Code* of generated Code object.
691 instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag)); 776 instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag));
692 return; 777 return;
693 } 778 }
694 779
695 DCHECK(IsBranch(instr) || IsLui(instr)); 780 DCHECK(IsBranch(instr) || IsLui(instr));
696 if (IsBranch(instr)) { 781 if (IsBranch(instr)) {
697 int32_t imm18 = target_pos - (pos + kBranchPCOffset); 782 instr = SetBranchOffset(pos, target_pos, instr);
698 DCHECK((imm18 & 3) == 0); 783 instr_at_put(pos, instr);
699 784 } else {
700 instr &= ~kImm16Mask;
701 int32_t imm16 = imm18 >> 2;
702 DCHECK(is_int16(imm16));
703
704 instr_at_put(pos, instr | (imm16 & kImm16Mask));
705 } else if (IsLui(instr)) {
706 Instr instr_lui = instr_at(pos + 0 * Assembler::kInstrSize); 785 Instr instr_lui = instr_at(pos + 0 * Assembler::kInstrSize);
707 Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize); 786 Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize);
708 DCHECK(IsOri(instr_ori)); 787 DCHECK(IsOri(instr_ori));
ivica.bogosavljevic 2015/10/15 11:49:08 Since isLui is not part of else if, then we should
balazs.kilvady 2015/10/30 21:11:14 Check covered at line 780
709 uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos; 788 uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos;
710 DCHECK((imm & 3) == 0); 789 DCHECK((imm & 3) == 0);
711 790
712 instr_lui &= ~kImm16Mask; 791 instr_lui &= ~kImm16Mask;
713 instr_ori &= ~kImm16Mask; 792 instr_ori &= ~kImm16Mask;
714 793
715 instr_at_put(pos + 0 * Assembler::kInstrSize, 794 instr_at_put(pos + 0 * Assembler::kInstrSize,
716 instr_lui | ((imm & kHiMask) >> kLuiShift)); 795 instr_lui | ((imm & kHiMask) >> kLuiShift));
717 instr_at_put(pos + 1 * Assembler::kInstrSize, 796 instr_at_put(pos + 1 * Assembler::kInstrSize,
718 instr_ori | (imm & kImm16Mask)); 797 instr_ori | (imm & kImm16Mask));
719 } else {
720 UNREACHABLE();
721 } 798 }
722 } 799 }
723 800
724 801
725 void Assembler::print(Label* L) { 802 void Assembler::print(Label* L) {
726 if (L->is_unused()) { 803 if (L->is_unused()) {
727 PrintF("unused label\n"); 804 PrintF("unused label\n");
728 } else if (L->is_bound()) { 805 } else if (L->is_bound()) {
729 PrintF("bound label to %d\n", L->pos()); 806 PrintF("bound label to %d\n", L->pos());
730 } else if (L->is_linked()) { 807 } else if (L->is_linked()) {
(...skipping 28 matching lines...) Expand all
759 while (L->is_linked()) { 836 while (L->is_linked()) {
760 int32_t fixup_pos = L->pos(); 837 int32_t fixup_pos = L->pos();
761 int32_t dist = pos - fixup_pos; 838 int32_t dist = pos - fixup_pos;
762 is_internal = internal_reference_positions_.find(fixup_pos) != 839 is_internal = internal_reference_positions_.find(fixup_pos) !=
763 internal_reference_positions_.end(); 840 internal_reference_positions_.end();
764 next(L, is_internal); // Call next before overwriting link with target at 841 next(L, is_internal); // Call next before overwriting link with target at
765 // fixup_pos. 842 // fixup_pos.
766 Instr instr = instr_at(fixup_pos); 843 Instr instr = instr_at(fixup_pos);
767 if (is_internal) { 844 if (is_internal) {
768 target_at_put(fixup_pos, pos, is_internal); 845 target_at_put(fixup_pos, pos, is_internal);
769 } else if (!is_internal && IsBranch(instr)) { 846 } else {
770 if (dist > kMaxBranchOffset) { 847 if (IsBranch(instr)) {
771 if (trampoline_pos == kInvalidSlotPos) { 848 if (dist > kMaxBranchOffset) {
772 trampoline_pos = get_trampoline_entry(fixup_pos); 849 if (trampoline_pos == kInvalidSlotPos) {
773 CHECK(trampoline_pos != kInvalidSlotPos); 850 trampoline_pos = get_trampoline_entry(fixup_pos);
851 CHECK(trampoline_pos != kInvalidSlotPos);
852 }
853 CHECK((trampoline_pos - fixup_pos) <= kMaxBranchOffset);
854 target_at_put(fixup_pos, trampoline_pos, false);
855 fixup_pos = trampoline_pos;
856 dist = pos - fixup_pos;
774 } 857 }
775 CHECK((trampoline_pos - fixup_pos) <= kMaxBranchOffset); 858 target_at_put(fixup_pos, pos, false);
776 target_at_put(fixup_pos, trampoline_pos, false); 859 } else {
777 fixup_pos = trampoline_pos; 860 target_at_put(fixup_pos, pos, false);
778 dist = pos - fixup_pos;
779 } 861 }
780 target_at_put(fixup_pos, pos, false);
781 } else {
782 target_at_put(fixup_pos, pos, false);
783 } 862 }
784 } 863 }
785 L->bind_to(pos); 864 L->bind_to(pos);
786 865
787 // Keep track of the last bound label so we don't eliminate any instructions 866 // Keep track of the last bound label so we don't eliminate any instructions
788 // before a bound label. 867 // before a bound label.
789 if (pos > last_bound_pos_) 868 if (pos > last_bound_pos_)
790 last_bound_pos_ = pos; 869 last_bound_pos_ = pos;
791 } 870 }
792 871
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
992 } 1071 }
993 } 1072 }
994 1073
995 uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos; 1074 uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos;
996 DCHECK((imm & 3) == 0); 1075 DCHECK((imm & 3) == 0);
997 1076
998 return imm; 1077 return imm;
999 } 1078 }
1000 1079
1001 1080
1002 int32_t Assembler::branch_offset(Label* L, bool jump_elimination_allowed) { 1081 int32_t Assembler::branch_offset_helper(Label* L, bool jump_elimination_allowed,
ivica.bogosavljevic 2015/10/15 11:49:08 Bravo for removing all these functions!
1082 int bits) {
1003 int32_t target_pos; 1083 int32_t target_pos;
1084 int32_t pad = IsPrevInstrCompactBranch() ? kInstrSize : 0;
1004 1085
1005 if (L->is_bound()) { 1086 if (L->is_bound()) {
1006 target_pos = L->pos(); 1087 target_pos = L->pos();
1007 } else { 1088 } else {
1008 if (L->is_linked()) { 1089 if (L->is_linked()) {
1009 target_pos = L->pos(); 1090 target_pos = L->pos();
1010 L->link_to(pc_offset()); 1091 L->link_to(pc_offset() + pad);
1011 } else { 1092 } else {
1012 L->link_to(pc_offset()); 1093 L->link_to(pc_offset() + pad);
1013 if (!trampoline_emitted_) { 1094 if (!trampoline_emitted_) {
1014 unbound_labels_count_++; 1095 unbound_labels_count_++;
1015 next_buffer_check_ -= kTrampolineSlotsSize; 1096 next_buffer_check_ -= kTrampolineSlotsSize;
1016 }
1017 return kEndOfChain;
1018 }
1019 }
1020
1021 int32_t offset = target_pos - (pc_offset() + kBranchPCOffset);
1022 DCHECK((offset & 3) == 0);
1023 DCHECK(is_int16(offset >> 2));
1024
1025 return offset;
1026 }
1027
1028
1029 int32_t Assembler::branch_offset_compact(Label* L,
1030 bool jump_elimination_allowed) {
1031 int32_t target_pos;
1032 if (L->is_bound()) {
1033 target_pos = L->pos();
1034 } else {
1035 if (L->is_linked()) {
1036 target_pos = L->pos();
1037 L->link_to(pc_offset());
1038 } else {
1039 L->link_to(pc_offset());
1040 if (!trampoline_emitted_) {
1041 unbound_labels_count_++;
1042 next_buffer_check_ -= kTrampolineSlotsSize;
1043 }
1044 return kEndOfChain;
1045 }
1046 }
1047
1048 int32_t offset = target_pos - pc_offset();
1049 DCHECK((offset & 3) == 0);
1050 DCHECK(is_int16(offset >> 2));
1051
1052 return offset;
1053 }
1054
1055
1056 int32_t Assembler::branch_offset21(Label* L, bool jump_elimination_allowed) {
1057 int32_t target_pos;
1058
1059 if (L->is_bound()) {
1060 target_pos = L->pos();
1061 } else {
1062 if (L->is_linked()) {
1063 target_pos = L->pos();
1064 L->link_to(pc_offset());
1065 } else {
1066 L->link_to(pc_offset());
1067 if (!trampoline_emitted_) {
1068 unbound_labels_count_++;
1069 next_buffer_check_ -= kTrampolineSlotsSize;
1070 } 1097 }
1071 return kEndOfChain; 1098 return kEndOfChain;
1072 } 1099 }
1073 } 1100 }
1074 1101
1075 int32_t offset = target_pos - (pc_offset() + kBranchPCOffset); 1102 int32_t offset = target_pos - (pc_offset() + kBranchPCOffset + pad);
1103 DCHECK(is_intn(offset, bits + 2));
1076 DCHECK((offset & 3) == 0); 1104 DCHECK((offset & 3) == 0);
1077 DCHECK(((offset >> 2) & 0xFFE00000) == 0); // Offset is 21bit width.
1078 1105
1079 return offset; 1106 return offset;
1080 } 1107 }
1081
1082
1083 int32_t Assembler::branch_offset21_compact(Label* L,
1084 bool jump_elimination_allowed) {
1085 int32_t target_pos;
1086
1087 if (L->is_bound()) {
1088 target_pos = L->pos();
1089 } else {
1090 if (L->is_linked()) {
1091 target_pos = L->pos();
1092 L->link_to(pc_offset());
1093 } else {
1094 L->link_to(pc_offset());
1095 if (!trampoline_emitted_) {
1096 unbound_labels_count_++;
1097 next_buffer_check_ -= kTrampolineSlotsSize;
1098 }
1099 return kEndOfChain;
1100 }
1101 }
1102
1103 int32_t offset = target_pos - pc_offset();
1104 DCHECK((offset & 3) == 0);
1105 DCHECK(((offset >> 2) & 0xFFe00000) == 0); // Offset is 21bit width.
1106
1107 return offset;
1108 }
1109 1108
1110 1109
1111 void Assembler::label_at_put(Label* L, int at_offset) { 1110 void Assembler::label_at_put(Label* L, int at_offset) {
1112 int target_pos; 1111 int target_pos;
1113 if (L->is_bound()) { 1112 if (L->is_bound()) {
1114 target_pos = L->pos(); 1113 target_pos = L->pos();
1115 instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag)); 1114 instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag));
1116 } else { 1115 } else {
1117 if (L->is_linked()) { 1116 if (L->is_linked()) {
1118 target_pos = L->pos(); // L's link. 1117 target_pos = L->pos(); // L's link.
(...skipping 16 matching lines...) Expand all
1135 1134
1136 1135
1137 //------- Branch and jump instructions -------- 1136 //------- Branch and jump instructions --------
1138 1137
1139 void Assembler::b(int16_t offset) { 1138 void Assembler::b(int16_t offset) {
1140 beq(zero_reg, zero_reg, offset); 1139 beq(zero_reg, zero_reg, offset);
1141 } 1140 }
1142 1141
1143 1142
1144 void Assembler::bal(int16_t offset) { 1143 void Assembler::bal(int16_t offset) {
1145 positions_recorder()->WriteRecordedPositions();
1146 bgezal(zero_reg, offset); 1144 bgezal(zero_reg, offset);
1147 } 1145 }
1148 1146
1149 1147
1150 void Assembler::bc(int32_t offset) { 1148 void Assembler::bc(int32_t offset) {
1151 DCHECK(IsMipsArchVariant(kMips32r6)); 1149 DCHECK(IsMipsArchVariant(kMips32r6));
1152 GenInstrImmediate(BC, offset); 1150 GenInstrImmediate(BC, offset);
1151 EmittedCompactBranchInstruction();
1153 } 1152 }
1154 1153
1155 1154
1156 void Assembler::balc(int32_t offset) { 1155 void Assembler::balc(int32_t offset) {
1157 DCHECK(IsMipsArchVariant(kMips32r6)); 1156 DCHECK(IsMipsArchVariant(kMips32r6));
1158 positions_recorder()->WriteRecordedPositions();
1159 GenInstrImmediate(BALC, offset); 1157 GenInstrImmediate(BALC, offset);
1158 EmittedCompactBranchInstruction();
1160 } 1159 }
1161 1160
1162 1161
1163 void Assembler::beq(Register rs, Register rt, int16_t offset) { 1162 void Assembler::beq(Register rs, Register rt, int16_t offset) {
1164 BlockTrampolinePoolScope block_trampoline_pool(this); 1163 BlockTrampolinePoolScope block_trampoline_pool(this);
1165 GenInstrImmediate(BEQ, rs, rt, offset); 1164 GenInstrImmediate(BEQ, rs, rt, offset);
1166 BlockTrampolinePoolFor(1); // For associated delay slot. 1165 BlockTrampolinePoolFor(1); // For associated delay slot.
1167 } 1166 }
1168 1167
1169 1168
1170 void Assembler::bgez(Register rs, int16_t offset) { 1169 void Assembler::bgez(Register rs, int16_t offset) {
1171 BlockTrampolinePoolScope block_trampoline_pool(this); 1170 BlockTrampolinePoolScope block_trampoline_pool(this);
1172 GenInstrImmediate(REGIMM, rs, BGEZ, offset); 1171 GenInstrImmediate(REGIMM, rs, BGEZ, offset);
1173 BlockTrampolinePoolFor(1); // For associated delay slot. 1172 BlockTrampolinePoolFor(1); // For associated delay slot.
1174 } 1173 }
1175 1174
1176 1175
1177 void Assembler::bgezc(Register rt, int16_t offset) { 1176 void Assembler::bgezc(Register rt, int16_t offset) {
1178 DCHECK(IsMipsArchVariant(kMips32r6)); 1177 DCHECK(IsMipsArchVariant(kMips32r6));
1179 DCHECK(!(rt.is(zero_reg))); 1178 DCHECK(!(rt.is(zero_reg)));
1180 GenInstrImmediate(BLEZL, rt, rt, offset); 1179 GenInstrImmediate(BLEZL, rt, rt, offset);
1180 EmittedCompactBranchInstruction();
1181 } 1181 }
1182 1182
1183 1183
1184 void Assembler::bgeuc(Register rs, Register rt, int16_t offset) { 1184 void Assembler::bgeuc(Register rs, Register rt, int16_t offset) {
1185 DCHECK(IsMipsArchVariant(kMips32r6)); 1185 DCHECK(IsMipsArchVariant(kMips32r6));
1186 DCHECK(!(rs.is(zero_reg))); 1186 DCHECK(!(rs.is(zero_reg)));
1187 DCHECK(!(rt.is(zero_reg))); 1187 DCHECK(!(rt.is(zero_reg)));
1188 DCHECK(rs.code() != rt.code()); 1188 DCHECK(rs.code() != rt.code());
1189 GenInstrImmediate(BLEZ, rs, rt, offset); 1189 GenInstrImmediate(BLEZ, rs, rt, offset);
1190 EmittedCompactBranchInstruction();
1190 } 1191 }
1191 1192
1192 1193
1193 void Assembler::bgec(Register rs, Register rt, int16_t offset) { 1194 void Assembler::bgec(Register rs, Register rt, int16_t offset) {
1194 DCHECK(IsMipsArchVariant(kMips32r6)); 1195 DCHECK(IsMipsArchVariant(kMips32r6));
1195 DCHECK(!(rs.is(zero_reg))); 1196 DCHECK(!(rs.is(zero_reg)));
1196 DCHECK(!(rt.is(zero_reg))); 1197 DCHECK(!(rt.is(zero_reg)));
1197 DCHECK(rs.code() != rt.code()); 1198 DCHECK(rs.code() != rt.code());
1198 GenInstrImmediate(BLEZL, rs, rt, offset); 1199 GenInstrImmediate(BLEZL, rs, rt, offset);
1200 EmittedCompactBranchInstruction();
1199 } 1201 }
1200 1202
1201 1203
1202 void Assembler::bgezal(Register rs, int16_t offset) { 1204 void Assembler::bgezal(Register rs, int16_t offset) {
1203 DCHECK(!IsMipsArchVariant(kMips32r6) || rs.is(zero_reg)); 1205 DCHECK(!IsMipsArchVariant(kMips32r6) || rs.is(zero_reg));
1204 BlockTrampolinePoolScope block_trampoline_pool(this); 1206 BlockTrampolinePoolScope block_trampoline_pool(this);
1205 positions_recorder()->WriteRecordedPositions();
1206 GenInstrImmediate(REGIMM, rs, BGEZAL, offset); 1207 GenInstrImmediate(REGIMM, rs, BGEZAL, offset);
1207 BlockTrampolinePoolFor(1); // For associated delay slot. 1208 BlockTrampolinePoolFor(1); // For associated delay slot.
1208 } 1209 }
1209 1210
1210 1211
1211 void Assembler::bgtz(Register rs, int16_t offset) { 1212 void Assembler::bgtz(Register rs, int16_t offset) {
1212 BlockTrampolinePoolScope block_trampoline_pool(this); 1213 BlockTrampolinePoolScope block_trampoline_pool(this);
1213 GenInstrImmediate(BGTZ, rs, zero_reg, offset); 1214 GenInstrImmediate(BGTZ, rs, zero_reg, offset);
1214 BlockTrampolinePoolFor(1); // For associated delay slot. 1215 BlockTrampolinePoolFor(1); // For associated delay slot.
1215 } 1216 }
1216 1217
1217 1218
1218 void Assembler::bgtzc(Register rt, int16_t offset) { 1219 void Assembler::bgtzc(Register rt, int16_t offset) {
1219 DCHECK(IsMipsArchVariant(kMips32r6)); 1220 DCHECK(IsMipsArchVariant(kMips32r6));
1220 DCHECK(!(rt.is(zero_reg))); 1221 DCHECK(!(rt.is(zero_reg)));
1221 GenInstrImmediate(BGTZL, zero_reg, rt, offset); 1222 GenInstrImmediate(BGTZL, zero_reg, rt, offset);
1223 EmittedCompactBranchInstruction();
1222 } 1224 }
1223 1225
1224 1226
1225 void Assembler::blez(Register rs, int16_t offset) { 1227 void Assembler::blez(Register rs, int16_t offset) {
1226 BlockTrampolinePoolScope block_trampoline_pool(this); 1228 BlockTrampolinePoolScope block_trampoline_pool(this);
1227 GenInstrImmediate(BLEZ, rs, zero_reg, offset); 1229 GenInstrImmediate(BLEZ, rs, zero_reg, offset);
1228 BlockTrampolinePoolFor(1); // For associated delay slot. 1230 BlockTrampolinePoolFor(1); // For associated delay slot.
1229 } 1231 }
1230 1232
1231 1233
1232 void Assembler::blezc(Register rt, int16_t offset) { 1234 void Assembler::blezc(Register rt, int16_t offset) {
1233 DCHECK(IsMipsArchVariant(kMips32r6)); 1235 DCHECK(IsMipsArchVariant(kMips32r6));
1234 DCHECK(!(rt.is(zero_reg))); 1236 DCHECK(!(rt.is(zero_reg)));
1235 GenInstrImmediate(BLEZL, zero_reg, rt, offset); 1237 GenInstrImmediate(BLEZL, zero_reg, rt, offset);
1238 EmittedCompactBranchInstruction();
1236 } 1239 }
1237 1240
1238 1241
1239 void Assembler::bltzc(Register rt, int16_t offset) { 1242 void Assembler::bltzc(Register rt, int16_t offset) {
1240 DCHECK(IsMipsArchVariant(kMips32r6)); 1243 DCHECK(IsMipsArchVariant(kMips32r6));
1241 DCHECK(!(rt.is(zero_reg))); 1244 DCHECK(!rt.is(zero_reg));
1242 GenInstrImmediate(BGTZL, rt, rt, offset); 1245 GenInstrImmediate(BGTZL, rt, rt, offset);
1246 EmittedCompactBranchInstruction();
1243 } 1247 }
1244 1248
1245 1249
1246 void Assembler::bltuc(Register rs, Register rt, int16_t offset) { 1250 void Assembler::bltuc(Register rs, Register rt, int16_t offset) {
1247 DCHECK(IsMipsArchVariant(kMips32r6)); 1251 DCHECK(IsMipsArchVariant(kMips32r6));
1248 DCHECK(!(rs.is(zero_reg))); 1252 DCHECK(!(rs.is(zero_reg)));
1249 DCHECK(!(rt.is(zero_reg))); 1253 DCHECK(!(rt.is(zero_reg)));
1250 DCHECK(rs.code() != rt.code()); 1254 DCHECK(rs.code() != rt.code());
1251 GenInstrImmediate(BGTZ, rs, rt, offset); 1255 GenInstrImmediate(BGTZ, rs, rt, offset);
1256 EmittedCompactBranchInstruction();
1252 } 1257 }
1253 1258
1254 1259
1255 void Assembler::bltc(Register rs, Register rt, int16_t offset) { 1260 void Assembler::bltc(Register rs, Register rt, int16_t offset) {
1256 DCHECK(IsMipsArchVariant(kMips32r6)); 1261 DCHECK(IsMipsArchVariant(kMips32r6));
1257 DCHECK(!(rs.is(zero_reg))); 1262 DCHECK(!rs.is(zero_reg));
1258 DCHECK(!(rt.is(zero_reg))); 1263 DCHECK(!rt.is(zero_reg));
1259 DCHECK(rs.code() != rt.code()); 1264 DCHECK(rs.code() != rt.code());
1260 GenInstrImmediate(BGTZL, rs, rt, offset); 1265 GenInstrImmediate(BGTZL, rs, rt, offset);
1266 EmittedCompactBranchInstruction();
1261 } 1267 }
1262 1268
1263 1269
1264 void Assembler::bltz(Register rs, int16_t offset) { 1270 void Assembler::bltz(Register rs, int16_t offset) {
1265 BlockTrampolinePoolScope block_trampoline_pool(this); 1271 BlockTrampolinePoolScope block_trampoline_pool(this);
1266 GenInstrImmediate(REGIMM, rs, BLTZ, offset); 1272 GenInstrImmediate(REGIMM, rs, BLTZ, offset);
1267 BlockTrampolinePoolFor(1); // For associated delay slot. 1273 BlockTrampolinePoolFor(1); // For associated delay slot.
1268 } 1274 }
1269 1275
1270 1276
1271 void Assembler::bltzal(Register rs, int16_t offset) { 1277 void Assembler::bltzal(Register rs, int16_t offset) {
1272 DCHECK(!IsMipsArchVariant(kMips32r6) || rs.is(zero_reg)); 1278 DCHECK(!IsMipsArchVariant(kMips32r6) || rs.is(zero_reg));
1273 BlockTrampolinePoolScope block_trampoline_pool(this); 1279 BlockTrampolinePoolScope block_trampoline_pool(this);
1274 positions_recorder()->WriteRecordedPositions();
1275 GenInstrImmediate(REGIMM, rs, BLTZAL, offset); 1280 GenInstrImmediate(REGIMM, rs, BLTZAL, offset);
1276 BlockTrampolinePoolFor(1); // For associated delay slot. 1281 BlockTrampolinePoolFor(1); // For associated delay slot.
1277 } 1282 }
1278 1283
1279 1284
1280 void Assembler::bne(Register rs, Register rt, int16_t offset) { 1285 void Assembler::bne(Register rs, Register rt, int16_t offset) {
1281 BlockTrampolinePoolScope block_trampoline_pool(this); 1286 BlockTrampolinePoolScope block_trampoline_pool(this);
1282 GenInstrImmediate(BNE, rs, rt, offset); 1287 GenInstrImmediate(BNE, rs, rt, offset);
1283 BlockTrampolinePoolFor(1); // For associated delay slot. 1288 BlockTrampolinePoolFor(1); // For associated delay slot.
1284 } 1289 }
1285 1290
1286 1291
1287 void Assembler::bovc(Register rs, Register rt, int16_t offset) { 1292 void Assembler::bovc(Register rs, Register rt, int16_t offset) {
1288 DCHECK(IsMipsArchVariant(kMips32r6)); 1293 DCHECK(IsMipsArchVariant(kMips32r6));
1289 DCHECK(!(rs.is(zero_reg))); 1294 DCHECK(!(rs.is(zero_reg)));
1290 DCHECK(rs.code() >= rt.code()); 1295 DCHECK(rs.code() >= rt.code());
1291 GenInstrImmediate(ADDI, rs, rt, offset); 1296 GenInstrImmediate(ADDI, rs, rt, offset);
1297 EmittedCompactBranchInstruction();
1292 } 1298 }
1293 1299
1294 1300
1295 void Assembler::bnvc(Register rs, Register rt, int16_t offset) { 1301 void Assembler::bnvc(Register rs, Register rt, int16_t offset) {
1296 DCHECK(IsMipsArchVariant(kMips32r6)); 1302 DCHECK(IsMipsArchVariant(kMips32r6));
1297 DCHECK(!(rs.is(zero_reg))); 1303 DCHECK(!(rs.is(zero_reg)));
1298 DCHECK(rs.code() >= rt.code()); 1304 DCHECK(rs.code() >= rt.code());
1299 GenInstrImmediate(DADDI, rs, rt, offset); 1305 GenInstrImmediate(DADDI, rs, rt, offset);
1306 EmittedCompactBranchInstruction();
1300 } 1307 }
1301 1308
1302 1309
1303 void Assembler::blezalc(Register rt, int16_t offset) { 1310 void Assembler::blezalc(Register rt, int16_t offset) {
1304 DCHECK(IsMipsArchVariant(kMips32r6)); 1311 DCHECK(IsMipsArchVariant(kMips32r6));
1305 DCHECK(!(rt.is(zero_reg))); 1312 DCHECK(!(rt.is(zero_reg)));
1306 GenInstrImmediate(BLEZ, zero_reg, rt, offset); 1313 GenInstrImmediate(BLEZ, zero_reg, rt, offset);
1314 EmittedCompactBranchInstruction();
1307 } 1315 }
1308 1316
1309 1317
1310 void Assembler::bgezalc(Register rt, int16_t offset) { 1318 void Assembler::bgezalc(Register rt, int16_t offset) {
1311 DCHECK(IsMipsArchVariant(kMips32r6)); 1319 DCHECK(IsMipsArchVariant(kMips32r6));
1312 DCHECK(!(rt.is(zero_reg))); 1320 DCHECK(!(rt.is(zero_reg)));
1313 GenInstrImmediate(BLEZ, rt, rt, offset); 1321 GenInstrImmediate(BLEZ, rt, rt, offset);
1322 EmittedCompactBranchInstruction();
1314 } 1323 }
1315 1324
1316 1325
1317 void Assembler::bgezall(Register rs, int16_t offset) { 1326 void Assembler::bgezall(Register rs, int16_t offset) {
1318 DCHECK(IsMipsArchVariant(kMips32r6)); 1327 DCHECK(IsMipsArchVariant(kMips32r6));
1319 DCHECK(!(rs.is(zero_reg))); 1328 DCHECK(!(rs.is(zero_reg)));
1320 GenInstrImmediate(REGIMM, rs, BGEZALL, offset); 1329 GenInstrImmediate(REGIMM, rs, BGEZALL, offset);
1321 } 1330 }
1322 1331
1323 1332
1324 void Assembler::bltzalc(Register rt, int16_t offset) { 1333 void Assembler::bltzalc(Register rt, int16_t offset) {
1325 DCHECK(IsMipsArchVariant(kMips32r6)); 1334 DCHECK(IsMipsArchVariant(kMips32r6));
1326 DCHECK(!(rt.is(zero_reg))); 1335 DCHECK(!(rt.is(zero_reg)));
1327 GenInstrImmediate(BGTZ, rt, rt, offset); 1336 GenInstrImmediate(BGTZ, rt, rt, offset);
1337 EmittedCompactBranchInstruction();
1328 } 1338 }
1329 1339
1330 1340
1331 void Assembler::bgtzalc(Register rt, int16_t offset) { 1341 void Assembler::bgtzalc(Register rt, int16_t offset) {
1332 DCHECK(IsMipsArchVariant(kMips32r6)); 1342 DCHECK(IsMipsArchVariant(kMips32r6));
1333 DCHECK(!(rt.is(zero_reg))); 1343 DCHECK(!(rt.is(zero_reg)));
1334 GenInstrImmediate(BGTZ, zero_reg, rt, offset); 1344 GenInstrImmediate(BGTZ, zero_reg, rt, offset);
1345 EmittedCompactBranchInstruction();
1335 } 1346 }
1336 1347
1337 1348
1338 void Assembler::beqzalc(Register rt, int16_t offset) { 1349 void Assembler::beqzalc(Register rt, int16_t offset) {
1339 DCHECK(IsMipsArchVariant(kMips32r6)); 1350 DCHECK(IsMipsArchVariant(kMips32r6));
1340 DCHECK(!(rt.is(zero_reg))); 1351 DCHECK(!(rt.is(zero_reg)));
1341 GenInstrImmediate(ADDI, zero_reg, rt, offset); 1352 GenInstrImmediate(ADDI, zero_reg, rt, offset);
1353 EmittedCompactBranchInstruction();
1342 } 1354 }
1343 1355
1344 1356
1345 void Assembler::bnezalc(Register rt, int16_t offset) { 1357 void Assembler::bnezalc(Register rt, int16_t offset) {
1346 DCHECK(IsMipsArchVariant(kMips32r6)); 1358 DCHECK(IsMipsArchVariant(kMips32r6));
1347 DCHECK(!(rt.is(zero_reg))); 1359 DCHECK(!(rt.is(zero_reg)));
1348 GenInstrImmediate(DADDI, zero_reg, rt, offset); 1360 GenInstrImmediate(DADDI, zero_reg, rt, offset);
1361 EmittedCompactBranchInstruction();
1349 } 1362 }
1350 1363
1351 1364
1352 void Assembler::beqc(Register rs, Register rt, int16_t offset) { 1365 void Assembler::beqc(Register rs, Register rt, int16_t offset) {
1353 DCHECK(IsMipsArchVariant(kMips32r6)); 1366 DCHECK(IsMipsArchVariant(kMips32r6));
1354 DCHECK(rs.code() < rt.code()); 1367 DCHECK(rs.code() != rt.code() && rs.code() != 0 && rt.code() != 0);
1355 GenInstrImmediate(ADDI, rs, rt, offset); 1368 if (rs.code() < rt.code()) {
1369 GenInstrImmediate(ADDI, rs, rt, offset);
1370 } else {
1371 GenInstrImmediate(ADDI, rt, rs, offset);
1372 }
1373 EmittedCompactBranchInstruction();
1356 } 1374 }
1357 1375
1358 1376
1359 void Assembler::beqzc(Register rs, int32_t offset) { 1377 void Assembler::beqzc(Register rs, int32_t offset) {
1360 DCHECK(IsMipsArchVariant(kMips32r6)); 1378 DCHECK(IsMipsArchVariant(kMips32r6));
1361 DCHECK(!(rs.is(zero_reg))); 1379 DCHECK(!(rs.is(zero_reg)));
1362 Instr instr = POP66 | (rs.code() << kRsShift) | (offset & kImm21Mask); 1380 Instr instr = POP66 | (rs.code() << kRsShift) | (offset & kImm21Mask);
1363 emit(instr); 1381 emit(instr);
1382 EmittedCompactBranchInstruction();
1364 } 1383 }
1365 1384
1366 1385
1367 void Assembler::bnec(Register rs, Register rt, int16_t offset) { 1386 void Assembler::bnec(Register rs, Register rt, int16_t offset) {
1368 DCHECK(IsMipsArchVariant(kMips32r6)); 1387 DCHECK(IsMipsArchVariant(kMips32r6));
1369 DCHECK(rs.code() < rt.code()); 1388 DCHECK(rs.code() != rt.code() && rs.code() != 0 && rt.code() != 0);
1370 GenInstrImmediate(DADDI, rs, rt, offset); 1389 if (rs.code() < rt.code()) {
1390 GenInstrImmediate(DADDI, rs, rt, offset);
1391 } else {
1392 GenInstrImmediate(DADDI, rt, rs, offset);
1393 }
1394 EmittedCompactBranchInstruction();
1371 } 1395 }
1372 1396
1373 1397
1374 void Assembler::bnezc(Register rs, int32_t offset) { 1398 void Assembler::bnezc(Register rs, int32_t offset) {
1375 DCHECK(IsMipsArchVariant(kMips32r6)); 1399 DCHECK(IsMipsArchVariant(kMips32r6));
1376 DCHECK(!(rs.is(zero_reg))); 1400 DCHECK(!(rs.is(zero_reg)));
1377 Instr instr = POP76 | (rs.code() << kRsShift) | offset; 1401 Instr instr = POP76 | (rs.code() << kRsShift) | (offset & kImm21Mask);
1378 emit(instr); 1402 emit(instr);
1403 EmittedCompactBranchInstruction();
1379 } 1404 }
1380 1405
1381 1406
1382 void Assembler::j(int32_t target) { 1407 void Assembler::j(int32_t target) {
1383 #if DEBUG 1408 #if DEBUG
1384 // Get pc of delay slot. 1409 // Get pc of delay slot.
1385 uint32_t ipc = reinterpret_cast<uint32_t>(pc_ + 1 * kInstrSize); 1410 uint32_t ipc = reinterpret_cast<uint32_t>(pc_ + 1 * kInstrSize);
1386 bool in_range = ((ipc ^ static_cast<uint32_t>(target)) >> 1411 bool in_range = ((ipc ^ static_cast<uint32_t>(target)) >>
1387 (kImm26Bits + kImmFieldShift)) == 0; 1412 (kImm26Bits + kImmFieldShift)) == 0;
1388 DCHECK(in_range && ((target & 3) == 0)); 1413 DCHECK(in_range && ((target & 3) == 0));
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1425 GenInstrRegister(SPECIAL, rs, zero_reg, rd, 0, JALR); 1450 GenInstrRegister(SPECIAL, rs, zero_reg, rd, 0, JALR);
1426 BlockTrampolinePoolFor(1); // For associated delay slot. 1451 BlockTrampolinePoolFor(1); // For associated delay slot.
1427 } 1452 }
1428 1453
1429 1454
1430 void Assembler::jic(Register rt, int16_t offset) { 1455 void Assembler::jic(Register rt, int16_t offset) {
1431 DCHECK(IsMipsArchVariant(kMips32r6)); 1456 DCHECK(IsMipsArchVariant(kMips32r6));
1432 Instr instr = POP66 | (JIC << kRsShift) | (rt.code() << kRtShift) | 1457 Instr instr = POP66 | (JIC << kRsShift) | (rt.code() << kRtShift) |
1433 (offset & kImm16Mask); 1458 (offset & kImm16Mask);
1434 emit(instr); 1459 emit(instr);
1460 EmittedCompactBranchInstruction();
1435 } 1461 }
1436 1462
1437 1463
1438 void Assembler::jialc(Register rt, int16_t offset) { 1464 void Assembler::jialc(Register rt, int16_t offset) {
1439 DCHECK(IsMipsArchVariant(kMips32r6)); 1465 DCHECK(IsMipsArchVariant(kMips32r6));
1440 positions_recorder()->WriteRecordedPositions();
1441 GenInstrImmediate(POP76, zero_reg, rt, offset); 1466 GenInstrImmediate(POP76, zero_reg, rt, offset);
1467 EmittedCompactBranchInstruction();
1442 } 1468 }
1443 1469
1444 1470
1445 // -------Data-processing-instructions--------- 1471 // -------Data-processing-instructions---------
1446 1472
1447 // Arithmetic. 1473 // Arithmetic.
1448 1474
1449 void Assembler::addu(Register rd, Register rs, Register rt) { 1475 void Assembler::addu(Register rd, Register rs, Register rt) {
1450 GenInstrRegister(SPECIAL, rs, rt, rd, 0, ADDU); 1476 GenInstrRegister(SPECIAL, rs, rt, rd, 0, ADDU);
1451 } 1477 }
(...skipping 1212 matching lines...) Expand 10 before | Expand all | Expand 10 after
2664 } 2690 }
2665 2691
2666 2692
2667 void Assembler::bc1t(int16_t offset, uint16_t cc) { 2693 void Assembler::bc1t(int16_t offset, uint16_t cc) {
2668 DCHECK(is_uint3(cc)); 2694 DCHECK(is_uint3(cc));
2669 Instr instr = COP1 | BC1 | cc << 18 | 1 << 16 | (offset & kImm16Mask); 2695 Instr instr = COP1 | BC1 | cc << 18 | 1 << 16 | (offset & kImm16Mask);
2670 emit(instr); 2696 emit(instr);
2671 } 2697 }
2672 2698
2673 2699
2674 // Debugging.
2675 int Assembler::RelocateInternalReference(RelocInfo::Mode rmode, byte* pc, 2700 int Assembler::RelocateInternalReference(RelocInfo::Mode rmode, byte* pc,
2676 intptr_t pc_delta) { 2701 intptr_t pc_delta) {
2677 Instr instr = instr_at(pc); 2702 Instr instr = instr_at(pc);
2678 2703
2679 if (RelocInfo::IsInternalReference(rmode)) { 2704 if (RelocInfo::IsInternalReference(rmode)) {
2680 int32_t* p = reinterpret_cast<int32_t*>(pc); 2705 int32_t* p = reinterpret_cast<int32_t*>(pc);
2681 if (*p == 0) { 2706 if (*p == 0) {
2682 return 0; // Number of instructions patched. 2707 return 0; // Number of instructions patched.
2683 } 2708 }
2684 *p += pc_delta; 2709 *p += pc_delta;
(...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after
3074 if (patched) { 3099 if (patched) {
3075 CpuFeatures::FlushICache(pc + 2, sizeof(Address)); 3100 CpuFeatures::FlushICache(pc + 2, sizeof(Address));
3076 } 3101 }
3077 } 3102 }
3078 3103
3079 3104
3080 } // namespace internal 3105 } // namespace internal
3081 } // namespace v8 3106 } // namespace v8
3082 3107
3083 #endif // V8_TARGET_ARCH_MIPS 3108 #endif // V8_TARGET_ARCH_MIPS
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698