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 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |