OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |