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

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: Created 5 years, 1 month 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
« no previous file with comments | « src/mips/assembler-mips.h ('k') | src/mips/assembler-mips-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 267 matching lines...) Expand 10 before | Expand all | Expand 10 after
278 278
279 trampoline_emitted_ = FLAG_force_long_branches; 279 trampoline_emitted_ = FLAG_force_long_branches;
280 unbound_labels_count_ = 0; 280 unbound_labels_count_ = 0;
281 block_buffer_growth_ = false; 281 block_buffer_growth_ = false;
282 282
283 ClearRecordedAstId(); 283 ClearRecordedAstId();
284 } 284 }
285 285
286 286
287 void Assembler::GetCode(CodeDesc* desc) { 287 void Assembler::GetCode(CodeDesc* desc) {
288 if (IsPrevInstrCompactBranch()) {
289 nop();
290 ClearCompactBranchState();
291 }
288 DCHECK(pc_ <= reloc_info_writer.pos()); // No overlap. 292 DCHECK(pc_ <= reloc_info_writer.pos()); // No overlap.
289 // Set up code descriptor. 293 // Set up code descriptor.
290 desc->buffer = buffer_; 294 desc->buffer = buffer_;
291 desc->buffer_size = buffer_size_; 295 desc->buffer_size = buffer_size_;
292 desc->instr_size = pc_offset(); 296 desc->instr_size = pc_offset();
293 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); 297 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
294 desc->origin = this; 298 desc->origin = this;
295 } 299 }
296 300
297 301
298 void Assembler::Align(int m) { 302 void Assembler::Align(int m) {
299 DCHECK(m >= 4 && base::bits::IsPowerOfTwo32(m)); 303 DCHECK(m >= 4 && base::bits::IsPowerOfTwo32(m));
304 if (IsPrevInstrCompactBranch()) {
305 nop();
306 ClearCompactBranchState();
307 }
300 while ((pc_offset() & (m - 1)) != 0) { 308 while ((pc_offset() & (m - 1)) != 0) {
301 nop(); 309 nop();
302 } 310 }
303 } 311 }
304 312
305 313
306 void Assembler::CodeTargetAlign() { 314 void Assembler::CodeTargetAlign() {
307 // No advantage to aligning branch/call targets to more than 315 // No advantage to aligning branch/call targets to more than
308 // single instruction, that I am aware of. 316 // single instruction, that I am aware of.
309 Align(4); 317 Align(4);
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
446 const int kEndOfChain = -4; 454 const int kEndOfChain = -4;
447 // Determines the end of the Jump chain (a subset of the label link chain). 455 // Determines the end of the Jump chain (a subset of the label link chain).
448 const int kEndOfJumpChain = 0; 456 const int kEndOfJumpChain = 0;
449 457
450 458
451 bool Assembler::IsBranch(Instr instr) { 459 bool Assembler::IsBranch(Instr instr) {
452 uint32_t opcode = GetOpcodeField(instr); 460 uint32_t opcode = GetOpcodeField(instr);
453 uint32_t rt_field = GetRtField(instr); 461 uint32_t rt_field = GetRtField(instr);
454 uint32_t rs_field = GetRsField(instr); 462 uint32_t rs_field = GetRsField(instr);
455 // Checks if the instruction is a branch. 463 // Checks if the instruction is a branch.
456 return opcode == BEQ || 464 bool isBranch =
457 opcode == BNE || 465 opcode == BEQ || opcode == BNE || opcode == BLEZ || opcode == BGTZ ||
458 opcode == BLEZ || 466 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 || 467 (opcode == REGIMM && (rt_field == BLTZ || rt_field == BGEZ ||
465 rt_field == BLTZAL || rt_field == BGEZAL)) || 468 rt_field == BLTZAL || rt_field == BGEZAL)) ||
466 (opcode == COP1 && rs_field == BC1) || // Coprocessor branch. 469 (opcode == COP1 && rs_field == BC1) || // Coprocessor branch.
467 (opcode == COP1 && rs_field == BC1EQZ) || 470 (opcode == COP1 && rs_field == BC1EQZ) ||
468 (opcode == COP1 && rs_field == BC1NEZ); 471 (opcode == COP1 && rs_field == BC1NEZ);
472 if (!isBranch && IsMipsArchVariant(kMips32r6)) {
473 // All the 3 variants of POP10 (BOVC, BEQC, BEQZALC) and
474 // POP30 (BNVC, BNEC, BNEZALC) are branch ops.
475 isBranch |= opcode == POP10 || opcode == POP30 || opcode == BC ||
476 opcode == BALC ||
477 (opcode == POP66 && rs_field != 0) || // BEQZC
478 (opcode == POP76 && rs_field != 0); // BNEZC
479 }
480 return isBranch;
469 } 481 }
470 482
471 483
484 bool Assembler::IsBc(Instr instr) {
485 uint32_t opcode = GetOpcodeField(instr);
486 // Checks if the instruction is a BC or BALC.
487 return opcode == BC || opcode == BALC;
488 }
489
490
491 bool Assembler::IsBzc(Instr instr) {
492 uint32_t opcode = GetOpcodeField(instr);
493 // Checks if the instruction is BEQZC or BNEZC.
494 return (opcode == POP66 && GetRsField(instr) != 0) ||
495 (opcode == POP76 && GetRsField(instr) != 0);
496 }
497
498
472 bool Assembler::IsEmittedConstant(Instr instr) { 499 bool Assembler::IsEmittedConstant(Instr instr) {
473 uint32_t label_constant = GetLabelConst(instr); 500 uint32_t label_constant = GetLabelConst(instr);
474 return label_constant == 0; // Emitted label const in reg-exp engine. 501 return label_constant == 0; // Emitted label const in reg-exp engine.
475 } 502 }
476 503
477 504
478 bool Assembler::IsBeq(Instr instr) { 505 bool Assembler::IsBeq(Instr instr) {
479 return GetOpcodeField(instr) == BEQ; 506 return GetOpcodeField(instr) == BEQ;
480 } 507 }
481 508
482 509
483 bool Assembler::IsBne(Instr instr) { 510 bool Assembler::IsBne(Instr instr) {
484 return GetOpcodeField(instr) == BNE; 511 return GetOpcodeField(instr) == BNE;
485 } 512 }
486 513
487 514
515 bool Assembler::IsBeqzc(Instr instr) {
516 uint32_t opcode = GetOpcodeField(instr);
517 return opcode == POP66 && GetRsField(instr) != 0;
518 }
519
520
521 bool Assembler::IsBnezc(Instr instr) {
522 uint32_t opcode = GetOpcodeField(instr);
523 return opcode == POP76 && GetRsField(instr) != 0;
524 }
525
526
527 bool Assembler::IsBeqc(Instr instr) {
528 uint32_t opcode = GetOpcodeField(instr);
529 uint32_t rs = GetRsField(instr);
530 uint32_t rt = GetRtField(instr);
531 return opcode == POP10 && rs != 0 && rs < rt; // && rt != 0
532 }
533
534
535 bool Assembler::IsBnec(Instr instr) {
536 uint32_t opcode = GetOpcodeField(instr);
537 uint32_t rs = GetRsField(instr);
538 uint32_t rt = GetRtField(instr);
539 return opcode == POP30 && rs != 0 && rs < rt; // && rt != 0
540 }
541
542
488 bool Assembler::IsJump(Instr instr) { 543 bool Assembler::IsJump(Instr instr) {
489 uint32_t opcode = GetOpcodeField(instr); 544 uint32_t opcode = GetOpcodeField(instr);
490 uint32_t rt_field = GetRtField(instr); 545 uint32_t rt_field = GetRtField(instr);
491 uint32_t rd_field = GetRdField(instr); 546 uint32_t rd_field = GetRdField(instr);
492 uint32_t function_field = GetFunctionField(instr); 547 uint32_t function_field = GetFunctionField(instr);
493 // Checks if the instruction is a jump. 548 // Checks if the instruction is a jump.
494 return opcode == J || opcode == JAL || 549 return opcode == J || opcode == JAL ||
495 (opcode == SPECIAL && rt_field == 0 && 550 (opcode == SPECIAL && rt_field == 0 &&
496 ((function_field == JALR) || (rd_field == 0 && (function_field == JR)))); 551 ((function_field == JALR) || (rd_field == 0 && (function_field == JR))));
497 } 552 }
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
563 } 618 }
564 619
565 620
566 int32_t Assembler::GetBranchOffset(Instr instr) { 621 int32_t Assembler::GetBranchOffset(Instr instr) {
567 DCHECK(IsBranch(instr)); 622 DCHECK(IsBranch(instr));
568 return (static_cast<int16_t>(instr & kImm16Mask)) << 2; 623 return (static_cast<int16_t>(instr & kImm16Mask)) << 2;
569 } 624 }
570 625
571 626
572 bool Assembler::IsLw(Instr instr) { 627 bool Assembler::IsLw(Instr instr) {
573 return ((instr & kOpcodeMask) == LW); 628 return (static_cast<uint32_t>(instr & kOpcodeMask) == LW);
574 } 629 }
575 630
576 631
577 int16_t Assembler::GetLwOffset(Instr instr) { 632 int16_t Assembler::GetLwOffset(Instr instr) {
578 DCHECK(IsLw(instr)); 633 DCHECK(IsLw(instr));
579 return ((instr & kImm16Mask)); 634 return ((instr & kImm16Mask));
580 } 635 }
581 636
582 637
583 Instr Assembler::SetLwOffset(Instr instr, int16_t offset) { 638 Instr Assembler::SetLwOffset(Instr instr, int16_t offset) {
584 DCHECK(IsLw(instr)); 639 DCHECK(IsLw(instr));
585 640
586 // We actually create a new lw instruction based on the original one. 641 // We actually create a new lw instruction based on the original one.
587 Instr temp_instr = LW | (instr & kRsFieldMask) | (instr & kRtFieldMask) 642 Instr temp_instr = LW | (instr & kRsFieldMask) | (instr & kRtFieldMask)
588 | (offset & kImm16Mask); 643 | (offset & kImm16Mask);
589 644
590 return temp_instr; 645 return temp_instr;
591 } 646 }
592 647
593 648
594 bool Assembler::IsSw(Instr instr) { 649 bool Assembler::IsSw(Instr instr) {
595 return ((instr & kOpcodeMask) == SW); 650 return (static_cast<uint32_t>(instr & kOpcodeMask) == SW);
596 } 651 }
597 652
598 653
599 Instr Assembler::SetSwOffset(Instr instr, int16_t offset) { 654 Instr Assembler::SetSwOffset(Instr instr, int16_t offset) {
600 DCHECK(IsSw(instr)); 655 DCHECK(IsSw(instr));
601 return ((instr & ~kImm16Mask) | (offset & kImm16Mask)); 656 return ((instr & ~kImm16Mask) | (offset & kImm16Mask));
602 } 657 }
603 658
604 659
605 bool Assembler::IsAddImmediate(Instr instr) { 660 bool Assembler::IsAddImmediate(Instr instr) {
606 return ((instr & kOpcodeMask) == ADDIU); 661 return ((instr & kOpcodeMask) == ADDIU);
607 } 662 }
608 663
609 664
610 Instr Assembler::SetAddImmediateOffset(Instr instr, int16_t offset) { 665 Instr Assembler::SetAddImmediateOffset(Instr instr, int16_t offset) {
611 DCHECK(IsAddImmediate(instr)); 666 DCHECK(IsAddImmediate(instr));
612 return ((instr & ~kImm16Mask) | (offset & kImm16Mask)); 667 return ((instr & ~kImm16Mask) | (offset & kImm16Mask));
613 } 668 }
614 669
615 670
616 bool Assembler::IsAndImmediate(Instr instr) { 671 bool Assembler::IsAndImmediate(Instr instr) {
617 return GetOpcodeField(instr) == ANDI; 672 return GetOpcodeField(instr) == ANDI;
618 } 673 }
619 674
620 675
676 static Assembler::OffsetSize OffsetSizeInBits(Instr instr) {
677 if (IsMipsArchVariant(kMips32r6)) {
678 if (Assembler::IsBc(instr)) {
679 return Assembler::OffsetSize::kOffset26;
680 } else if (Assembler::IsBzc(instr)) {
681 return Assembler::OffsetSize::kOffset21;
682 }
683 }
684 return Assembler::OffsetSize::kOffset16;
685 }
686
687
688 static inline int32_t AddBranchOffset(int pos, Instr instr) {
689 int bits = OffsetSizeInBits(instr);
690 const int32_t mask = (1 << bits) - 1;
691 bits = 32 - bits;
692
693 // Do NOT change this to <<2. We rely on arithmetic shifts here, assuming
694 // the compiler uses arithmetic shifts for signed integers.
695 int32_t imm = ((instr & mask) << bits) >> (bits - 2);
696
697 if (imm == kEndOfChain) {
698 // EndOfChain sentinel is returned directly, not relative to pc or pos.
699 return kEndOfChain;
700 } else {
701 return pos + Assembler::kBranchPCOffset + imm;
702 }
703 }
704
705
621 int Assembler::target_at(int pos, bool is_internal) { 706 int Assembler::target_at(int pos, bool is_internal) {
622 Instr instr = instr_at(pos); 707 Instr instr = instr_at(pos);
623 if (is_internal) { 708 if (is_internal) {
624 if (instr == 0) { 709 if (instr == 0) {
625 return kEndOfChain; 710 return kEndOfChain;
626 } else { 711 } else {
627 int32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos); 712 int32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos);
628 int delta = static_cast<int>(instr_address - instr); 713 int delta = static_cast<int>(instr_address - instr);
629 DCHECK(pos > delta); 714 DCHECK(pos > delta);
630 return pos - delta; 715 return pos - delta;
631 } 716 }
632 } 717 }
633 if ((instr & ~kImm16Mask) == 0) { 718 if ((instr & ~kImm16Mask) == 0) {
634 // Emitted label constant, not part of a branch. 719 // Emitted label constant, not part of a branch.
635 if (instr == 0) { 720 if (instr == 0) {
636 return kEndOfChain; 721 return kEndOfChain;
637 } else { 722 } else {
638 int32_t imm18 =((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14; 723 int32_t imm18 =((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14;
639 return (imm18 + pos); 724 return (imm18 + pos);
640 } 725 }
641 } 726 }
642 // Check we have a branch or jump instruction. 727 // Check we have a branch or jump instruction.
643 DCHECK(IsBranch(instr) || IsLui(instr)); 728 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)) { 729 if (IsBranch(instr)) {
647 int32_t imm18 = ((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14; 730 return AddBranchOffset(pos, instr);
648 731 } 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); 732 Instr instr_lui = instr_at(pos + 0 * Assembler::kInstrSize);
657 Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize); 733 Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize);
658 DCHECK(IsOri(instr_ori)); 734 DCHECK(IsOri(instr_ori));
659 int32_t imm = (instr_lui & static_cast<int32_t>(kImm16Mask)) << kLuiShift; 735 int32_t imm = (instr_lui & static_cast<int32_t>(kImm16Mask)) << kLuiShift;
660 imm |= (instr_ori & static_cast<int32_t>(kImm16Mask)); 736 imm |= (instr_ori & static_cast<int32_t>(kImm16Mask));
661 737
662 if (imm == kEndOfJumpChain) { 738 if (imm == kEndOfJumpChain) {
663 // EndOfChain sentinel is returned directly, not relative to pc or pos. 739 // EndOfChain sentinel is returned directly, not relative to pc or pos.
664 return kEndOfChain; 740 return kEndOfChain;
665 } else { 741 } else {
666 uint32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos); 742 uint32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos);
667 int32_t delta = instr_address - imm; 743 int32_t delta = instr_address - imm;
668 DCHECK(pos > delta); 744 DCHECK(pos > delta);
669 return pos - delta; 745 return pos - delta;
670 } 746 }
671 } else {
672 UNREACHABLE();
673 return 0;
674 } 747 }
748 return 0;
675 } 749 }
676 750
677 751
752 static inline Instr SetBranchOffset(int32_t pos, int32_t target_pos,
753 Instr instr) {
754 int32_t bits = OffsetSizeInBits(instr);
755 int32_t imm = target_pos - (pos + Assembler::kBranchPCOffset);
756 DCHECK((imm & 3) == 0);
757 imm >>= 2;
758
759 const int32_t mask = (1 << bits) - 1;
760 instr &= ~mask;
761 DCHECK(is_intn(imm, bits));
762
763 return instr | (imm & mask);
764 }
765
766
678 void Assembler::target_at_put(int32_t pos, int32_t target_pos, 767 void Assembler::target_at_put(int32_t pos, int32_t target_pos,
679 bool is_internal) { 768 bool is_internal) {
680 Instr instr = instr_at(pos); 769 Instr instr = instr_at(pos);
681 770
682 if (is_internal) { 771 if (is_internal) {
683 uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos; 772 uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos;
684 instr_at_put(pos, imm); 773 instr_at_put(pos, imm);
685 return; 774 return;
686 } 775 }
687 if ((instr & ~kImm16Mask) == 0) { 776 if ((instr & ~kImm16Mask) == 0) {
688 DCHECK(target_pos == kEndOfChain || target_pos >= 0); 777 DCHECK(target_pos == kEndOfChain || target_pos >= 0);
689 // Emitted label constant, not part of a branch. 778 // Emitted label constant, not part of a branch.
690 // Make label relative to Code* of generated Code object. 779 // Make label relative to Code* of generated Code object.
691 instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag)); 780 instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag));
692 return; 781 return;
693 } 782 }
694 783
695 DCHECK(IsBranch(instr) || IsLui(instr)); 784 DCHECK(IsBranch(instr) || IsLui(instr));
696 if (IsBranch(instr)) { 785 if (IsBranch(instr)) {
697 int32_t imm18 = target_pos - (pos + kBranchPCOffset); 786 instr = SetBranchOffset(pos, target_pos, instr);
698 DCHECK((imm18 & 3) == 0); 787 instr_at_put(pos, instr);
699 788 } 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); 789 Instr instr_lui = instr_at(pos + 0 * Assembler::kInstrSize);
707 Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize); 790 Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize);
708 DCHECK(IsOri(instr_ori)); 791 DCHECK(IsOri(instr_ori));
709 uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos; 792 uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos;
710 DCHECK((imm & 3) == 0); 793 DCHECK((imm & 3) == 0);
711 794
712 instr_lui &= ~kImm16Mask; 795 instr_lui &= ~kImm16Mask;
713 instr_ori &= ~kImm16Mask; 796 instr_ori &= ~kImm16Mask;
714 797
715 instr_at_put(pos + 0 * Assembler::kInstrSize, 798 instr_at_put(pos + 0 * Assembler::kInstrSize,
716 instr_lui | ((imm & kHiMask) >> kLuiShift)); 799 instr_lui | ((imm & kHiMask) >> kLuiShift));
717 instr_at_put(pos + 1 * Assembler::kInstrSize, 800 instr_at_put(pos + 1 * Assembler::kInstrSize,
718 instr_ori | (imm & kImm16Mask)); 801 instr_ori | (imm & kImm16Mask));
719 } else {
720 UNREACHABLE();
721 } 802 }
722 } 803 }
723 804
724 805
725 void Assembler::print(Label* L) { 806 void Assembler::print(Label* L) {
726 if (L->is_unused()) { 807 if (L->is_unused()) {
727 PrintF("unused label\n"); 808 PrintF("unused label\n");
728 } else if (L->is_bound()) { 809 } else if (L->is_bound()) {
729 PrintF("bound label to %d\n", L->pos()); 810 PrintF("bound label to %d\n", L->pos());
730 } else if (L->is_linked()) { 811 } else if (L->is_linked()) {
(...skipping 28 matching lines...) Expand all
759 while (L->is_linked()) { 840 while (L->is_linked()) {
760 int32_t fixup_pos = L->pos(); 841 int32_t fixup_pos = L->pos();
761 int32_t dist = pos - fixup_pos; 842 int32_t dist = pos - fixup_pos;
762 is_internal = internal_reference_positions_.find(fixup_pos) != 843 is_internal = internal_reference_positions_.find(fixup_pos) !=
763 internal_reference_positions_.end(); 844 internal_reference_positions_.end();
764 next(L, is_internal); // Call next before overwriting link with target at 845 next(L, is_internal); // Call next before overwriting link with target at
765 // fixup_pos. 846 // fixup_pos.
766 Instr instr = instr_at(fixup_pos); 847 Instr instr = instr_at(fixup_pos);
767 if (is_internal) { 848 if (is_internal) {
768 target_at_put(fixup_pos, pos, is_internal); 849 target_at_put(fixup_pos, pos, is_internal);
769 } else if (!is_internal && IsBranch(instr)) { 850 } else {
770 if (dist > kMaxBranchOffset) { 851 if (IsBranch(instr)) {
771 if (trampoline_pos == kInvalidSlotPos) { 852 if (dist > kMaxBranchOffset) {
772 trampoline_pos = get_trampoline_entry(fixup_pos); 853 if (trampoline_pos == kInvalidSlotPos) {
773 CHECK(trampoline_pos != kInvalidSlotPos); 854 trampoline_pos = get_trampoline_entry(fixup_pos);
855 CHECK(trampoline_pos != kInvalidSlotPos);
856 }
857 CHECK((trampoline_pos - fixup_pos) <= kMaxBranchOffset);
858 target_at_put(fixup_pos, trampoline_pos, false);
859 fixup_pos = trampoline_pos;
860 dist = pos - fixup_pos;
774 } 861 }
775 CHECK((trampoline_pos - fixup_pos) <= kMaxBranchOffset); 862 target_at_put(fixup_pos, pos, false);
776 target_at_put(fixup_pos, trampoline_pos, false); 863 } else {
777 fixup_pos = trampoline_pos; 864 target_at_put(fixup_pos, pos, false);
778 dist = pos - fixup_pos;
779 } 865 }
780 target_at_put(fixup_pos, pos, false);
781 } else {
782 target_at_put(fixup_pos, pos, false);
783 } 866 }
784 } 867 }
785 L->bind_to(pos); 868 L->bind_to(pos);
786 869
787 // Keep track of the last bound label so we don't eliminate any instructions 870 // Keep track of the last bound label so we don't eliminate any instructions
788 // before a bound label. 871 // before a bound label.
789 if (pos > last_bound_pos_) 872 if (pos > last_bound_pos_)
790 last_bound_pos_ = pos; 873 last_bound_pos_ = pos;
791 } 874 }
792 875
(...skipping 10 matching lines...) Expand all
803 if (link == kEndOfChain) { 886 if (link == kEndOfChain) {
804 L->Unuse(); 887 L->Unuse();
805 } else { 888 } else {
806 DCHECK(link >= 0); 889 DCHECK(link >= 0);
807 L->link_to(link); 890 L->link_to(link);
808 } 891 }
809 } 892 }
810 893
811 894
812 bool Assembler::is_near(Label* L) { 895 bool Assembler::is_near(Label* L) {
813 if (L->is_bound()) { 896 DCHECK(L->is_bound());
814 return ((pc_offset() - L->pos()) < kMaxBranchOffset - 4 * kInstrSize); 897 return ((pc_offset() - L->pos()) < kMaxBranchOffset - 4 * kInstrSize);
815 }
816 return false;
817 } 898 }
818 899
819 900
901 bool Assembler::is_near(Label* L, OffsetSize bits) {
902 if (L == nullptr || !L->is_bound()) return true;
903 return ((pc_offset() - L->pos()) <
904 (1 << (bits + 2 - 1)) - 1 - 5 * kInstrSize);
905 }
906
907
908 bool Assembler::is_near_branch(Label* L) {
909 DCHECK(L->is_bound());
910 int max_offset =
911 IsMipsArchVariant(kMips32r6) ? kMaxCompactBranchOffset : kMaxBranchOffset;
912 return pc_offset() - L->pos() < max_offset - 4 * kInstrSize;
913 }
914
915
820 // We have to use a temporary register for things that can be relocated even 916 // We have to use a temporary register for things that can be relocated even
821 // if they can be encoded in the MIPS's 16 bits of immediate-offset instruction 917 // if they can be encoded in the MIPS's 16 bits of immediate-offset instruction
822 // space. There is no guarantee that the relocated location can be similarly 918 // space. There is no guarantee that the relocated location can be similarly
823 // encoded. 919 // encoded.
824 bool Assembler::MustUseReg(RelocInfo::Mode rmode) { 920 bool Assembler::MustUseReg(RelocInfo::Mode rmode) {
825 return !RelocInfo::IsNone(rmode); 921 return !RelocInfo::IsNone(rmode);
826 } 922 }
827 923
828 void Assembler::GenInstrRegister(Opcode opcode, 924 void Assembler::GenInstrRegister(Opcode opcode,
829 Register rs, 925 Register rs,
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
897 SecondaryField func) { 993 SecondaryField func) {
898 DCHECK(fs.is_valid() && rt.is_valid()); 994 DCHECK(fs.is_valid() && rt.is_valid());
899 Instr instr = 995 Instr instr =
900 opcode | fmt | (rt.code() << kRtShift) | (fs.code() << kFsShift) | func; 996 opcode | fmt | (rt.code() << kRtShift) | (fs.code() << kFsShift) | func;
901 emit(instr); 997 emit(instr);
902 } 998 }
903 999
904 1000
905 // Instructions with immediate value. 1001 // Instructions with immediate value.
906 // Registers are in the order of the instruction encoding, from left to right. 1002 // Registers are in the order of the instruction encoding, from left to right.
907 void Assembler::GenInstrImmediate(Opcode opcode, 1003 void Assembler::GenInstrImmediate(Opcode opcode, Register rs, Register rt,
908 Register rs, 1004 int32_t j,
909 Register rt, 1005 CompactBranchType is_compact_branch) {
910 int32_t j) {
911 DCHECK(rs.is_valid() && rt.is_valid() && (is_int16(j) || is_uint16(j))); 1006 DCHECK(rs.is_valid() && rt.is_valid() && (is_int16(j) || is_uint16(j)));
912 Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift) 1007 Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift)
913 | (j & kImm16Mask); 1008 | (j & kImm16Mask);
1009 emit(instr, is_compact_branch);
1010 }
1011
1012
1013 void Assembler::GenInstrImmediate(Opcode opcode, Register rs, SecondaryField SF,
1014 int32_t j,
1015 CompactBranchType is_compact_branch) {
1016 DCHECK(rs.is_valid() && (is_int16(j) || is_uint16(j)));
1017 Instr instr = opcode | (rs.code() << kRsShift) | SF | (j & kImm16Mask);
1018 emit(instr, is_compact_branch);
1019 }
1020
1021
1022 void Assembler::GenInstrImmediate(Opcode opcode, Register rs, FPURegister ft,
1023 int32_t j,
1024 CompactBranchType is_compact_branch) {
1025 DCHECK(rs.is_valid() && ft.is_valid() && (is_int16(j) || is_uint16(j)));
1026 Instr instr = opcode | (rs.code() << kRsShift) | (ft.code() << kFtShift)
1027 | (j & kImm16Mask);
1028 emit(instr, is_compact_branch);
1029 }
1030
1031
1032 void Assembler::GenInstrImmediate(Opcode opcode, Register rs, int32_t offset21,
1033 CompactBranchType is_compact_branch) {
1034 DCHECK(rs.is_valid() && (is_int21(offset21)));
1035 Instr instr = opcode | (rs.code() << kRsShift) | (offset21 & kImm21Mask);
1036 emit(instr, is_compact_branch);
1037 }
1038
1039
1040 void Assembler::GenInstrImmediate(Opcode opcode, Register rs,
1041 uint32_t offset21) {
1042 DCHECK(rs.is_valid() && (is_uint21(offset21)));
1043 Instr instr = opcode | (rs.code() << kRsShift) | (offset21 & kImm21Mask);
914 emit(instr); 1044 emit(instr);
915 } 1045 }
916 1046
917 1047
918 void Assembler::GenInstrImmediate(Opcode opcode, 1048 void Assembler::GenInstrImmediate(Opcode opcode, int32_t offset26,
919 Register rs, 1049 CompactBranchType is_compact_branch) {
920 SecondaryField SF, 1050 DCHECK(is_int26(offset26));
921 int32_t j) { 1051 Instr instr = opcode | (offset26 & kImm26Mask);
922 DCHECK(rs.is_valid() && (is_int16(j) || is_uint16(j))); 1052 emit(instr, is_compact_branch);
923 Instr instr = opcode | (rs.code() << kRsShift) | SF | (j & kImm16Mask);
924 emit(instr);
925 } 1053 }
926 1054
927 1055
928 void Assembler::GenInstrImmediate(Opcode opcode,
929 Register rs,
930 FPURegister ft,
931 int32_t j) {
932 DCHECK(rs.is_valid() && ft.is_valid() && (is_int16(j) || is_uint16(j)));
933 Instr instr = opcode | (rs.code() << kRsShift) | (ft.code() << kFtShift)
934 | (j & kImm16Mask);
935 emit(instr);
936 }
937
938
939 void Assembler::GenInstrImmediate(Opcode opcode, Register rs, int32_t j) {
940 DCHECK(rs.is_valid() && (is_uint21(j)));
941 Instr instr = opcode | (rs.code() << kRsShift) | (j & kImm21Mask);
942 emit(instr);
943 }
944
945
946 void Assembler::GenInstrImmediate(Opcode opcode, int32_t offset26) {
947 DCHECK(is_int26(offset26));
948 Instr instr = opcode | (offset26 & kImm26Mask);
949 emit(instr);
950 }
951
952
953 void Assembler::GenInstrJump(Opcode opcode, 1056 void Assembler::GenInstrJump(Opcode opcode,
954 uint32_t address) { 1057 uint32_t address) {
955 BlockTrampolinePoolScope block_trampoline_pool(this); 1058 BlockTrampolinePoolScope block_trampoline_pool(this);
956 DCHECK(is_uint26(address)); 1059 DCHECK(is_uint26(address));
957 Instr instr = opcode | address; 1060 Instr instr = opcode | address;
958 emit(instr); 1061 emit(instr);
959 BlockTrampolinePoolFor(1); // For associated delay slot. 1062 BlockTrampolinePoolFor(1); // For associated delay slot.
960 } 1063 }
961 1064
962 1065
(...skipping 29 matching lines...) Expand all
992 } 1095 }
993 } 1096 }
994 1097
995 uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos; 1098 uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos;
996 DCHECK((imm & 3) == 0); 1099 DCHECK((imm & 3) == 0);
997 1100
998 return imm; 1101 return imm;
999 } 1102 }
1000 1103
1001 1104
1002 int32_t Assembler::branch_offset(Label* L, bool jump_elimination_allowed) { 1105 int32_t Assembler::branch_offset_helper(Label* L, OffsetSize bits) {
1003 int32_t target_pos; 1106 int32_t target_pos;
1107 int32_t pad = IsPrevInstrCompactBranch() ? kInstrSize : 0;
1004 1108
1005 if (L->is_bound()) { 1109 if (L->is_bound()) {
1006 target_pos = L->pos(); 1110 target_pos = L->pos();
1007 } else { 1111 } else {
1008 if (L->is_linked()) { 1112 if (L->is_linked()) {
1009 target_pos = L->pos(); 1113 target_pos = L->pos();
1010 L->link_to(pc_offset()); 1114 L->link_to(pc_offset() + pad);
1011 } else { 1115 } else {
1012 L->link_to(pc_offset()); 1116 L->link_to(pc_offset() + pad);
1013 if (!trampoline_emitted_) { 1117 if (!trampoline_emitted_) {
1014 unbound_labels_count_++; 1118 unbound_labels_count_++;
1015 next_buffer_check_ -= kTrampolineSlotsSize; 1119 next_buffer_check_ -= kTrampolineSlotsSize;
1016 } 1120 }
1017 return kEndOfChain; 1121 return kEndOfChain;
1018 } 1122 }
1019 } 1123 }
1020 1124
1021 int32_t offset = target_pos - (pc_offset() + kBranchPCOffset); 1125 int32_t offset = target_pos - (pc_offset() + kBranchPCOffset + pad);
1126 DCHECK(is_intn(offset, bits + 2));
1022 DCHECK((offset & 3) == 0); 1127 DCHECK((offset & 3) == 0);
1023 DCHECK(is_int16(offset >> 2));
1024 1128
1025 return offset; 1129 return offset;
1026 } 1130 }
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 }
1071 return kEndOfChain;
1072 }
1073 }
1074
1075 int32_t offset = target_pos - (pc_offset() + kBranchPCOffset);
1076 DCHECK((offset & 3) == 0);
1077 DCHECK(((offset >> 2) & 0xFFE00000) == 0); // Offset is 21bit width.
1078
1079 return offset;
1080 }
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 1131
1110 1132
1111 void Assembler::label_at_put(Label* L, int at_offset) { 1133 void Assembler::label_at_put(Label* L, int at_offset) {
1112 int target_pos; 1134 int target_pos;
1113 if (L->is_bound()) { 1135 if (L->is_bound()) {
1114 target_pos = L->pos(); 1136 target_pos = L->pos();
1115 instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag)); 1137 instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag));
1116 } else { 1138 } else {
1117 if (L->is_linked()) { 1139 if (L->is_linked()) {
1118 target_pos = L->pos(); // L's link. 1140 target_pos = L->pos(); // L's link.
(...skipping 23 matching lines...) Expand all
1142 1164
1143 1165
1144 void Assembler::bal(int16_t offset) { 1166 void Assembler::bal(int16_t offset) {
1145 positions_recorder()->WriteRecordedPositions(); 1167 positions_recorder()->WriteRecordedPositions();
1146 bgezal(zero_reg, offset); 1168 bgezal(zero_reg, offset);
1147 } 1169 }
1148 1170
1149 1171
1150 void Assembler::bc(int32_t offset) { 1172 void Assembler::bc(int32_t offset) {
1151 DCHECK(IsMipsArchVariant(kMips32r6)); 1173 DCHECK(IsMipsArchVariant(kMips32r6));
1152 GenInstrImmediate(BC, offset); 1174 GenInstrImmediate(BC, offset, CompactBranchType::COMPACT_BRANCH);
1153 } 1175 }
1154 1176
1155 1177
1156 void Assembler::balc(int32_t offset) { 1178 void Assembler::balc(int32_t offset) {
1157 DCHECK(IsMipsArchVariant(kMips32r6)); 1179 DCHECK(IsMipsArchVariant(kMips32r6));
1158 positions_recorder()->WriteRecordedPositions(); 1180 positions_recorder()->WriteRecordedPositions();
1159 GenInstrImmediate(BALC, offset); 1181 GenInstrImmediate(BALC, offset, CompactBranchType::COMPACT_BRANCH);
1160 } 1182 }
1161 1183
1162 1184
1163 void Assembler::beq(Register rs, Register rt, int16_t offset) { 1185 void Assembler::beq(Register rs, Register rt, int16_t offset) {
1164 BlockTrampolinePoolScope block_trampoline_pool(this); 1186 BlockTrampolinePoolScope block_trampoline_pool(this);
1165 GenInstrImmediate(BEQ, rs, rt, offset); 1187 GenInstrImmediate(BEQ, rs, rt, offset);
1166 BlockTrampolinePoolFor(1); // For associated delay slot. 1188 BlockTrampolinePoolFor(1); // For associated delay slot.
1167 } 1189 }
1168 1190
1169 1191
1170 void Assembler::bgez(Register rs, int16_t offset) { 1192 void Assembler::bgez(Register rs, int16_t offset) {
1171 BlockTrampolinePoolScope block_trampoline_pool(this); 1193 BlockTrampolinePoolScope block_trampoline_pool(this);
1172 GenInstrImmediate(REGIMM, rs, BGEZ, offset); 1194 GenInstrImmediate(REGIMM, rs, BGEZ, offset);
1173 BlockTrampolinePoolFor(1); // For associated delay slot. 1195 BlockTrampolinePoolFor(1); // For associated delay slot.
1174 } 1196 }
1175 1197
1176 1198
1177 void Assembler::bgezc(Register rt, int16_t offset) { 1199 void Assembler::bgezc(Register rt, int16_t offset) {
1178 DCHECK(IsMipsArchVariant(kMips32r6)); 1200 DCHECK(IsMipsArchVariant(kMips32r6));
1179 DCHECK(!(rt.is(zero_reg))); 1201 DCHECK(!(rt.is(zero_reg)));
1180 GenInstrImmediate(BLEZL, rt, rt, offset); 1202 GenInstrImmediate(BLEZL, rt, rt, offset, CompactBranchType::COMPACT_BRANCH);
1181 } 1203 }
1182 1204
1183 1205
1184 void Assembler::bgeuc(Register rs, Register rt, int16_t offset) { 1206 void Assembler::bgeuc(Register rs, Register rt, int16_t offset) {
1185 DCHECK(IsMipsArchVariant(kMips32r6)); 1207 DCHECK(IsMipsArchVariant(kMips32r6));
1186 DCHECK(!(rs.is(zero_reg))); 1208 DCHECK(!(rs.is(zero_reg)));
1187 DCHECK(!(rt.is(zero_reg))); 1209 DCHECK(!(rt.is(zero_reg)));
1188 DCHECK(rs.code() != rt.code()); 1210 DCHECK(rs.code() != rt.code());
1189 GenInstrImmediate(BLEZ, rs, rt, offset); 1211 GenInstrImmediate(BLEZ, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
1190 } 1212 }
1191 1213
1192 1214
1193 void Assembler::bgec(Register rs, Register rt, int16_t offset) { 1215 void Assembler::bgec(Register rs, Register rt, int16_t offset) {
1194 DCHECK(IsMipsArchVariant(kMips32r6)); 1216 DCHECK(IsMipsArchVariant(kMips32r6));
1195 DCHECK(!(rs.is(zero_reg))); 1217 DCHECK(!(rs.is(zero_reg)));
1196 DCHECK(!(rt.is(zero_reg))); 1218 DCHECK(!(rt.is(zero_reg)));
1197 DCHECK(rs.code() != rt.code()); 1219 DCHECK(rs.code() != rt.code());
1198 GenInstrImmediate(BLEZL, rs, rt, offset); 1220 GenInstrImmediate(BLEZL, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
1199 } 1221 }
1200 1222
1201 1223
1202 void Assembler::bgezal(Register rs, int16_t offset) { 1224 void Assembler::bgezal(Register rs, int16_t offset) {
1203 DCHECK(!IsMipsArchVariant(kMips32r6) || rs.is(zero_reg)); 1225 DCHECK(!IsMipsArchVariant(kMips32r6) || rs.is(zero_reg));
1204 BlockTrampolinePoolScope block_trampoline_pool(this); 1226 BlockTrampolinePoolScope block_trampoline_pool(this);
1205 positions_recorder()->WriteRecordedPositions(); 1227 positions_recorder()->WriteRecordedPositions();
1206 GenInstrImmediate(REGIMM, rs, BGEZAL, offset); 1228 GenInstrImmediate(REGIMM, rs, BGEZAL, offset);
1207 BlockTrampolinePoolFor(1); // For associated delay slot. 1229 BlockTrampolinePoolFor(1); // For associated delay slot.
1208 } 1230 }
1209 1231
1210 1232
1211 void Assembler::bgtz(Register rs, int16_t offset) { 1233 void Assembler::bgtz(Register rs, int16_t offset) {
1212 BlockTrampolinePoolScope block_trampoline_pool(this); 1234 BlockTrampolinePoolScope block_trampoline_pool(this);
1213 GenInstrImmediate(BGTZ, rs, zero_reg, offset); 1235 GenInstrImmediate(BGTZ, rs, zero_reg, offset);
1214 BlockTrampolinePoolFor(1); // For associated delay slot. 1236 BlockTrampolinePoolFor(1); // For associated delay slot.
1215 } 1237 }
1216 1238
1217 1239
1218 void Assembler::bgtzc(Register rt, int16_t offset) { 1240 void Assembler::bgtzc(Register rt, int16_t offset) {
1219 DCHECK(IsMipsArchVariant(kMips32r6)); 1241 DCHECK(IsMipsArchVariant(kMips32r6));
1220 DCHECK(!(rt.is(zero_reg))); 1242 DCHECK(!(rt.is(zero_reg)));
1221 GenInstrImmediate(BGTZL, zero_reg, rt, offset); 1243 GenInstrImmediate(BGTZL, zero_reg, rt, offset,
1244 CompactBranchType::COMPACT_BRANCH);
1222 } 1245 }
1223 1246
1224 1247
1225 void Assembler::blez(Register rs, int16_t offset) { 1248 void Assembler::blez(Register rs, int16_t offset) {
1226 BlockTrampolinePoolScope block_trampoline_pool(this); 1249 BlockTrampolinePoolScope block_trampoline_pool(this);
1227 GenInstrImmediate(BLEZ, rs, zero_reg, offset); 1250 GenInstrImmediate(BLEZ, rs, zero_reg, offset);
1228 BlockTrampolinePoolFor(1); // For associated delay slot. 1251 BlockTrampolinePoolFor(1); // For associated delay slot.
1229 } 1252 }
1230 1253
1231 1254
1232 void Assembler::blezc(Register rt, int16_t offset) { 1255 void Assembler::blezc(Register rt, int16_t offset) {
1233 DCHECK(IsMipsArchVariant(kMips32r6)); 1256 DCHECK(IsMipsArchVariant(kMips32r6));
1234 DCHECK(!(rt.is(zero_reg))); 1257 DCHECK(!(rt.is(zero_reg)));
1235 GenInstrImmediate(BLEZL, zero_reg, rt, offset); 1258 GenInstrImmediate(BLEZL, zero_reg, rt, offset,
1259 CompactBranchType::COMPACT_BRANCH);
1236 } 1260 }
1237 1261
1238 1262
1239 void Assembler::bltzc(Register rt, int16_t offset) { 1263 void Assembler::bltzc(Register rt, int16_t offset) {
1240 DCHECK(IsMipsArchVariant(kMips32r6)); 1264 DCHECK(IsMipsArchVariant(kMips32r6));
1241 DCHECK(!(rt.is(zero_reg))); 1265 DCHECK(!rt.is(zero_reg));
1242 GenInstrImmediate(BGTZL, rt, rt, offset); 1266 GenInstrImmediate(BGTZL, rt, rt, offset, CompactBranchType::COMPACT_BRANCH);
1243 } 1267 }
1244 1268
1245 1269
1246 void Assembler::bltuc(Register rs, Register rt, int16_t offset) { 1270 void Assembler::bltuc(Register rs, Register rt, int16_t offset) {
1247 DCHECK(IsMipsArchVariant(kMips32r6)); 1271 DCHECK(IsMipsArchVariant(kMips32r6));
1248 DCHECK(!(rs.is(zero_reg))); 1272 DCHECK(!(rs.is(zero_reg)));
1249 DCHECK(!(rt.is(zero_reg))); 1273 DCHECK(!(rt.is(zero_reg)));
1250 DCHECK(rs.code() != rt.code()); 1274 DCHECK(rs.code() != rt.code());
1251 GenInstrImmediate(BGTZ, rs, rt, offset); 1275 GenInstrImmediate(BGTZ, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
1252 } 1276 }
1253 1277
1254 1278
1255 void Assembler::bltc(Register rs, Register rt, int16_t offset) { 1279 void Assembler::bltc(Register rs, Register rt, int16_t offset) {
1256 DCHECK(IsMipsArchVariant(kMips32r6)); 1280 DCHECK(IsMipsArchVariant(kMips32r6));
1257 DCHECK(!(rs.is(zero_reg))); 1281 DCHECK(!rs.is(zero_reg));
1258 DCHECK(!(rt.is(zero_reg))); 1282 DCHECK(!rt.is(zero_reg));
1259 DCHECK(rs.code() != rt.code()); 1283 DCHECK(rs.code() != rt.code());
1260 GenInstrImmediate(BGTZL, rs, rt, offset); 1284 GenInstrImmediate(BGTZL, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
1261 } 1285 }
1262 1286
1263 1287
1264 void Assembler::bltz(Register rs, int16_t offset) { 1288 void Assembler::bltz(Register rs, int16_t offset) {
1265 BlockTrampolinePoolScope block_trampoline_pool(this); 1289 BlockTrampolinePoolScope block_trampoline_pool(this);
1266 GenInstrImmediate(REGIMM, rs, BLTZ, offset); 1290 GenInstrImmediate(REGIMM, rs, BLTZ, offset);
1267 BlockTrampolinePoolFor(1); // For associated delay slot. 1291 BlockTrampolinePoolFor(1); // For associated delay slot.
1268 } 1292 }
1269 1293
1270 1294
(...skipping 10 matching lines...) Expand all
1281 BlockTrampolinePoolScope block_trampoline_pool(this); 1305 BlockTrampolinePoolScope block_trampoline_pool(this);
1282 GenInstrImmediate(BNE, rs, rt, offset); 1306 GenInstrImmediate(BNE, rs, rt, offset);
1283 BlockTrampolinePoolFor(1); // For associated delay slot. 1307 BlockTrampolinePoolFor(1); // For associated delay slot.
1284 } 1308 }
1285 1309
1286 1310
1287 void Assembler::bovc(Register rs, Register rt, int16_t offset) { 1311 void Assembler::bovc(Register rs, Register rt, int16_t offset) {
1288 DCHECK(IsMipsArchVariant(kMips32r6)); 1312 DCHECK(IsMipsArchVariant(kMips32r6));
1289 DCHECK(!(rs.is(zero_reg))); 1313 DCHECK(!(rs.is(zero_reg)));
1290 DCHECK(rs.code() >= rt.code()); 1314 DCHECK(rs.code() >= rt.code());
1291 GenInstrImmediate(ADDI, rs, rt, offset); 1315 GenInstrImmediate(ADDI, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
1292 } 1316 }
1293 1317
1294 1318
1295 void Assembler::bnvc(Register rs, Register rt, int16_t offset) { 1319 void Assembler::bnvc(Register rs, Register rt, int16_t offset) {
1296 DCHECK(IsMipsArchVariant(kMips32r6)); 1320 DCHECK(IsMipsArchVariant(kMips32r6));
1297 DCHECK(!(rs.is(zero_reg))); 1321 DCHECK(!(rs.is(zero_reg)));
1298 DCHECK(rs.code() >= rt.code()); 1322 DCHECK(rs.code() >= rt.code());
1299 GenInstrImmediate(DADDI, rs, rt, offset); 1323 GenInstrImmediate(DADDI, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
1300 } 1324 }
1301 1325
1302 1326
1303 void Assembler::blezalc(Register rt, int16_t offset) { 1327 void Assembler::blezalc(Register rt, int16_t offset) {
1304 DCHECK(IsMipsArchVariant(kMips32r6)); 1328 DCHECK(IsMipsArchVariant(kMips32r6));
1305 DCHECK(!(rt.is(zero_reg))); 1329 DCHECK(!(rt.is(zero_reg)));
1306 GenInstrImmediate(BLEZ, zero_reg, rt, offset); 1330 positions_recorder()->WriteRecordedPositions();
1331 GenInstrImmediate(BLEZ, zero_reg, rt, offset,
1332 CompactBranchType::COMPACT_BRANCH);
1307 } 1333 }
1308 1334
1309 1335
1310 void Assembler::bgezalc(Register rt, int16_t offset) { 1336 void Assembler::bgezalc(Register rt, int16_t offset) {
1311 DCHECK(IsMipsArchVariant(kMips32r6)); 1337 DCHECK(IsMipsArchVariant(kMips32r6));
1312 DCHECK(!(rt.is(zero_reg))); 1338 DCHECK(!(rt.is(zero_reg)));
1313 GenInstrImmediate(BLEZ, rt, rt, offset); 1339 positions_recorder()->WriteRecordedPositions();
1340 GenInstrImmediate(BLEZ, rt, rt, offset, CompactBranchType::COMPACT_BRANCH);
1314 } 1341 }
1315 1342
1316 1343
1317 void Assembler::bgezall(Register rs, int16_t offset) { 1344 void Assembler::bgezall(Register rs, int16_t offset) {
1318 DCHECK(IsMipsArchVariant(kMips32r6)); 1345 DCHECK(IsMipsArchVariant(kMips32r6));
1319 DCHECK(!(rs.is(zero_reg))); 1346 DCHECK(!(rs.is(zero_reg)));
1347 positions_recorder()->WriteRecordedPositions();
1320 GenInstrImmediate(REGIMM, rs, BGEZALL, offset); 1348 GenInstrImmediate(REGIMM, rs, BGEZALL, offset);
1321 } 1349 }
1322 1350
1323 1351
1324 void Assembler::bltzalc(Register rt, int16_t offset) { 1352 void Assembler::bltzalc(Register rt, int16_t offset) {
1325 DCHECK(IsMipsArchVariant(kMips32r6)); 1353 DCHECK(IsMipsArchVariant(kMips32r6));
1326 DCHECK(!(rt.is(zero_reg))); 1354 DCHECK(!(rt.is(zero_reg)));
1327 GenInstrImmediate(BGTZ, rt, rt, offset); 1355 positions_recorder()->WriteRecordedPositions();
1356 GenInstrImmediate(BGTZ, rt, rt, offset, CompactBranchType::COMPACT_BRANCH);
1328 } 1357 }
1329 1358
1330 1359
1331 void Assembler::bgtzalc(Register rt, int16_t offset) { 1360 void Assembler::bgtzalc(Register rt, int16_t offset) {
1332 DCHECK(IsMipsArchVariant(kMips32r6)); 1361 DCHECK(IsMipsArchVariant(kMips32r6));
1333 DCHECK(!(rt.is(zero_reg))); 1362 DCHECK(!(rt.is(zero_reg)));
1334 GenInstrImmediate(BGTZ, zero_reg, rt, offset); 1363 positions_recorder()->WriteRecordedPositions();
1364 GenInstrImmediate(BGTZ, zero_reg, rt, offset,
1365 CompactBranchType::COMPACT_BRANCH);
1335 } 1366 }
1336 1367
1337 1368
1338 void Assembler::beqzalc(Register rt, int16_t offset) { 1369 void Assembler::beqzalc(Register rt, int16_t offset) {
1339 DCHECK(IsMipsArchVariant(kMips32r6)); 1370 DCHECK(IsMipsArchVariant(kMips32r6));
1340 DCHECK(!(rt.is(zero_reg))); 1371 DCHECK(!(rt.is(zero_reg)));
1341 GenInstrImmediate(ADDI, zero_reg, rt, offset); 1372 positions_recorder()->WriteRecordedPositions();
1373 GenInstrImmediate(ADDI, zero_reg, rt, offset,
1374 CompactBranchType::COMPACT_BRANCH);
1342 } 1375 }
1343 1376
1344 1377
1345 void Assembler::bnezalc(Register rt, int16_t offset) { 1378 void Assembler::bnezalc(Register rt, int16_t offset) {
1346 DCHECK(IsMipsArchVariant(kMips32r6)); 1379 DCHECK(IsMipsArchVariant(kMips32r6));
1347 DCHECK(!(rt.is(zero_reg))); 1380 DCHECK(!(rt.is(zero_reg)));
1348 GenInstrImmediate(DADDI, zero_reg, rt, offset); 1381 positions_recorder()->WriteRecordedPositions();
1382 GenInstrImmediate(DADDI, zero_reg, rt, offset,
1383 CompactBranchType::COMPACT_BRANCH);
1349 } 1384 }
1350 1385
1351 1386
1352 void Assembler::beqc(Register rs, Register rt, int16_t offset) { 1387 void Assembler::beqc(Register rs, Register rt, int16_t offset) {
1353 DCHECK(IsMipsArchVariant(kMips32r6)); 1388 DCHECK(IsMipsArchVariant(kMips32r6));
1354 DCHECK(rs.code() < rt.code()); 1389 DCHECK(rs.code() != rt.code() && rs.code() != 0 && rt.code() != 0);
1355 GenInstrImmediate(ADDI, rs, rt, offset); 1390 if (rs.code() < rt.code()) {
1391 GenInstrImmediate(ADDI, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
1392 } else {
1393 GenInstrImmediate(ADDI, rt, rs, offset, CompactBranchType::COMPACT_BRANCH);
1394 }
1356 } 1395 }
1357 1396
1358 1397
1359 void Assembler::beqzc(Register rs, int32_t offset) { 1398 void Assembler::beqzc(Register rs, int32_t offset) {
1360 DCHECK(IsMipsArchVariant(kMips32r6)); 1399 DCHECK(IsMipsArchVariant(kMips32r6));
1361 DCHECK(!(rs.is(zero_reg))); 1400 DCHECK(!(rs.is(zero_reg)));
1362 Instr instr = POP66 | (rs.code() << kRsShift) | (offset & kImm21Mask); 1401 GenInstrImmediate(POP66, rs, offset, CompactBranchType::COMPACT_BRANCH);
1363 emit(instr);
1364 } 1402 }
1365 1403
1366 1404
1367 void Assembler::bnec(Register rs, Register rt, int16_t offset) { 1405 void Assembler::bnec(Register rs, Register rt, int16_t offset) {
1368 DCHECK(IsMipsArchVariant(kMips32r6)); 1406 DCHECK(IsMipsArchVariant(kMips32r6));
1369 DCHECK(rs.code() < rt.code()); 1407 DCHECK(rs.code() != rt.code() && rs.code() != 0 && rt.code() != 0);
1370 GenInstrImmediate(DADDI, rs, rt, offset); 1408 if (rs.code() < rt.code()) {
1409 GenInstrImmediate(DADDI, rs, rt, offset, CompactBranchType::COMPACT_BRANCH);
1410 } else {
1411 GenInstrImmediate(DADDI, rt, rs, offset, CompactBranchType::COMPACT_BRANCH);
1412 }
1371 } 1413 }
1372 1414
1373 1415
1374 void Assembler::bnezc(Register rs, int32_t offset) { 1416 void Assembler::bnezc(Register rs, int32_t offset) {
1375 DCHECK(IsMipsArchVariant(kMips32r6)); 1417 DCHECK(IsMipsArchVariant(kMips32r6));
1376 DCHECK(!(rs.is(zero_reg))); 1418 DCHECK(!(rs.is(zero_reg)));
1377 Instr instr = POP76 | (rs.code() << kRsShift) | offset; 1419 GenInstrImmediate(POP76, rs, offset, CompactBranchType::COMPACT_BRANCH);
1378 emit(instr);
1379 } 1420 }
1380 1421
1381 1422
1382 void Assembler::j(int32_t target) { 1423 void Assembler::j(int32_t target) {
1383 #if DEBUG 1424 #if DEBUG
1384 // Get pc of delay slot. 1425 // Get pc of delay slot.
1385 uint32_t ipc = reinterpret_cast<uint32_t>(pc_ + 1 * kInstrSize); 1426 uint32_t ipc = reinterpret_cast<uint32_t>(pc_ + 1 * kInstrSize);
1386 bool in_range = ((ipc ^ static_cast<uint32_t>(target)) >> 1427 bool in_range = ((ipc ^ static_cast<uint32_t>(target)) >>
1387 (kImm26Bits + kImmFieldShift)) == 0; 1428 (kImm26Bits + kImmFieldShift)) == 0;
1388 DCHECK(in_range && ((target & 3) == 0)); 1429 DCHECK(in_range && ((target & 3) == 0));
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1422 DCHECK(rs.code() != rd.code()); 1463 DCHECK(rs.code() != rd.code());
1423 BlockTrampolinePoolScope block_trampoline_pool(this); 1464 BlockTrampolinePoolScope block_trampoline_pool(this);
1424 positions_recorder()->WriteRecordedPositions(); 1465 positions_recorder()->WriteRecordedPositions();
1425 GenInstrRegister(SPECIAL, rs, zero_reg, rd, 0, JALR); 1466 GenInstrRegister(SPECIAL, rs, zero_reg, rd, 0, JALR);
1426 BlockTrampolinePoolFor(1); // For associated delay slot. 1467 BlockTrampolinePoolFor(1); // For associated delay slot.
1427 } 1468 }
1428 1469
1429 1470
1430 void Assembler::jic(Register rt, int16_t offset) { 1471 void Assembler::jic(Register rt, int16_t offset) {
1431 DCHECK(IsMipsArchVariant(kMips32r6)); 1472 DCHECK(IsMipsArchVariant(kMips32r6));
1432 Instr instr = POP66 | (JIC << kRsShift) | (rt.code() << kRtShift) | 1473 GenInstrImmediate(POP66, zero_reg, rt, offset,
1433 (offset & kImm16Mask); 1474 CompactBranchType::COMPACT_BRANCH);
1434 emit(instr);
1435 } 1475 }
1436 1476
1437 1477
1438 void Assembler::jialc(Register rt, int16_t offset) { 1478 void Assembler::jialc(Register rt, int16_t offset) {
1439 DCHECK(IsMipsArchVariant(kMips32r6)); 1479 DCHECK(IsMipsArchVariant(kMips32r6));
1440 positions_recorder()->WriteRecordedPositions(); 1480 positions_recorder()->WriteRecordedPositions();
1441 GenInstrImmediate(POP76, zero_reg, rt, offset); 1481 GenInstrImmediate(POP76, zero_reg, rt, offset,
1482 CompactBranchType::COMPACT_BRANCH);
1442 } 1483 }
1443 1484
1444 1485
1445 // -------Data-processing-instructions--------- 1486 // -------Data-processing-instructions---------
1446 1487
1447 // Arithmetic. 1488 // Arithmetic.
1448 1489
1449 void Assembler::addu(Register rd, Register rs, Register rt) { 1490 void Assembler::addu(Register rd, Register rs, Register rt) {
1450 GenInstrRegister(SPECIAL, rs, rt, rd, 0, ADDU); 1491 GenInstrRegister(SPECIAL, rs, rt, rd, 0, ADDU);
1451 } 1492 }
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after
1755 DCHECK(is_uint16(j)); 1796 DCHECK(is_uint16(j));
1756 GenInstrImmediate(LUI, rs, rt, j); 1797 GenInstrImmediate(LUI, rs, rt, j);
1757 } 1798 }
1758 1799
1759 1800
1760 // ---------PC-Relative instructions----------- 1801 // ---------PC-Relative instructions-----------
1761 1802
1762 void Assembler::addiupc(Register rs, int32_t imm19) { 1803 void Assembler::addiupc(Register rs, int32_t imm19) {
1763 DCHECK(IsMipsArchVariant(kMips32r6)); 1804 DCHECK(IsMipsArchVariant(kMips32r6));
1764 DCHECK(rs.is_valid() && is_int19(imm19)); 1805 DCHECK(rs.is_valid() && is_int19(imm19));
1765 int32_t imm21 = ADDIUPC << kImm19Bits | (imm19 & kImm19Mask); 1806 uint32_t imm21 = ADDIUPC << kImm19Bits | (imm19 & kImm19Mask);
1766 GenInstrImmediate(PCREL, rs, imm21); 1807 GenInstrImmediate(PCREL, rs, imm21);
1767 } 1808 }
1768 1809
1769 1810
1770 void Assembler::lwpc(Register rs, int32_t offset19) { 1811 void Assembler::lwpc(Register rs, int32_t offset19) {
1771 DCHECK(IsMipsArchVariant(kMips32r6)); 1812 DCHECK(IsMipsArchVariant(kMips32r6));
1772 DCHECK(rs.is_valid() && is_int19(offset19)); 1813 DCHECK(rs.is_valid() && is_int19(offset19));
1773 int32_t imm21 = LWPC << kImm19Bits | (offset19 & kImm19Mask); 1814 uint32_t imm21 = LWPC << kImm19Bits | (offset19 & kImm19Mask);
1774 GenInstrImmediate(PCREL, rs, imm21); 1815 GenInstrImmediate(PCREL, rs, imm21);
1775 } 1816 }
1776 1817
1777 1818
1778 void Assembler::auipc(Register rs, int16_t imm16) { 1819 void Assembler::auipc(Register rs, int16_t imm16) {
1779 DCHECK(IsMipsArchVariant(kMips32r6)); 1820 DCHECK(IsMipsArchVariant(kMips32r6));
1780 DCHECK(rs.is_valid() && is_int16(imm16)); 1821 DCHECK(rs.is_valid() && is_int16(imm16));
1781 int32_t imm21 = AUIPC << kImm16Bits | (imm16 & kImm16Mask); 1822 uint32_t imm21 = AUIPC << kImm16Bits | (imm16 & kImm16Mask);
1782 GenInstrImmediate(PCREL, rs, imm21); 1823 GenInstrImmediate(PCREL, rs, imm21);
1783 } 1824 }
1784 1825
1785 1826
1786 void Assembler::aluipc(Register rs, int16_t imm16) { 1827 void Assembler::aluipc(Register rs, int16_t imm16) {
1787 DCHECK(IsMipsArchVariant(kMips32r6)); 1828 DCHECK(IsMipsArchVariant(kMips32r6));
1788 DCHECK(rs.is_valid() && is_int16(imm16)); 1829 DCHECK(rs.is_valid() && is_int16(imm16));
1789 int32_t imm21 = ALUIPC << kImm16Bits | (imm16 & kImm16Mask); 1830 uint32_t imm21 = ALUIPC << kImm16Bits | (imm16 & kImm16Mask);
1790 GenInstrImmediate(PCREL, rs, imm21); 1831 GenInstrImmediate(PCREL, rs, imm21);
1791 } 1832 }
1792 1833
1793 1834
1794 // -------------Misc-instructions-------------- 1835 // -------------Misc-instructions--------------
1795 1836
1796 // Break / Trap instructions. 1837 // Break / Trap instructions.
1797 void Assembler::break_(uint32_t code, bool break_as_stop) { 1838 void Assembler::break_(uint32_t code, bool break_as_stop) {
1798 DCHECK((code & ~0xfffff) == 0); 1839 DCHECK((code & ~0xfffff) == 0);
1799 // We need to invalidate breaks that could be stops as well because the 1840 // We need to invalidate breaks that could be stops as well because the
(...skipping 864 matching lines...) Expand 10 before | Expand all | Expand 10 after
2664 } 2705 }
2665 2706
2666 2707
2667 void Assembler::bc1t(int16_t offset, uint16_t cc) { 2708 void Assembler::bc1t(int16_t offset, uint16_t cc) {
2668 DCHECK(is_uint3(cc)); 2709 DCHECK(is_uint3(cc));
2669 Instr instr = COP1 | BC1 | cc << 18 | 1 << 16 | (offset & kImm16Mask); 2710 Instr instr = COP1 | BC1 | cc << 18 | 1 << 16 | (offset & kImm16Mask);
2670 emit(instr); 2711 emit(instr);
2671 } 2712 }
2672 2713
2673 2714
2674 // Debugging.
2675 int Assembler::RelocateInternalReference(RelocInfo::Mode rmode, byte* pc, 2715 int Assembler::RelocateInternalReference(RelocInfo::Mode rmode, byte* pc,
2676 intptr_t pc_delta) { 2716 intptr_t pc_delta) {
2677 Instr instr = instr_at(pc); 2717 Instr instr = instr_at(pc);
2678 2718
2679 if (RelocInfo::IsInternalReference(rmode)) { 2719 if (RelocInfo::IsInternalReference(rmode)) {
2680 int32_t* p = reinterpret_cast<int32_t*>(pc); 2720 int32_t* p = reinterpret_cast<int32_t*>(pc);
2681 if (*p == 0) { 2721 if (*p == 0) {
2682 return 0; // Number of instructions patched. 2722 return 0; // Number of instructions patched.
2683 } 2723 }
2684 *p += pc_delta; 2724 *p += pc_delta;
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
2858 } 2898 }
2859 return; 2899 return;
2860 } 2900 }
2861 2901
2862 DCHECK(!trampoline_emitted_); 2902 DCHECK(!trampoline_emitted_);
2863 DCHECK(unbound_labels_count_ >= 0); 2903 DCHECK(unbound_labels_count_ >= 0);
2864 if (unbound_labels_count_ > 0) { 2904 if (unbound_labels_count_ > 0) {
2865 // First we emit jump (2 instructions), then we emit trampoline pool. 2905 // First we emit jump (2 instructions), then we emit trampoline pool.
2866 { BlockTrampolinePoolScope block_trampoline_pool(this); 2906 { BlockTrampolinePoolScope block_trampoline_pool(this);
2867 Label after_pool; 2907 Label after_pool;
2868 b(&after_pool); 2908 if (IsMipsArchVariant(kMips32r6)) {
2869 nop(); 2909 bc(&after_pool);
2910 } else {
2911 b(&after_pool);
2912 nop();
2913 }
2870 2914
2871 int pool_start = pc_offset(); 2915 int pool_start = pc_offset();
2872 for (int i = 0; i < unbound_labels_count_; i++) { 2916 for (int i = 0; i < unbound_labels_count_; i++) {
2873 uint32_t imm32; 2917 uint32_t imm32;
2874 imm32 = jump_address(&after_pool); 2918 imm32 = jump_address(&after_pool);
2875 { BlockGrowBufferScope block_buf_growth(this); 2919 { BlockGrowBufferScope block_buf_growth(this);
2876 // Buffer growth (and relocation) must be blocked for internal 2920 // Buffer growth (and relocation) must be blocked for internal
2877 // references until associated instructions are emitted and available 2921 // references until associated instructions are emitted and available
2878 // to be patched. 2922 // to be patched.
2879 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE_ENCODED); 2923 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE_ENCODED);
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
3074 if (patched) { 3118 if (patched) {
3075 CpuFeatures::FlushICache(pc + 2, sizeof(Address)); 3119 CpuFeatures::FlushICache(pc + 2, sizeof(Address));
3076 } 3120 }
3077 } 3121 }
3078 3122
3079 3123
3080 } // namespace internal 3124 } // namespace internal
3081 } // namespace v8 3125 } // namespace v8
3082 3126
3083 #endif // V8_TARGET_ARCH_MIPS 3127 #endif // V8_TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « src/mips/assembler-mips.h ('k') | src/mips/assembler-mips-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698