Chromium Code Reviews| 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 523 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 534 | 534 |
| 535 | 535 |
| 536 bool Assembler::IsBnec(Instr instr) { | 536 bool Assembler::IsBnec(Instr instr) { |
| 537 uint32_t opcode = GetOpcodeField(instr); | 537 uint32_t opcode = GetOpcodeField(instr); |
| 538 uint32_t rs = GetRsField(instr); | 538 uint32_t rs = GetRsField(instr); |
| 539 uint32_t rt = GetRtField(instr); | 539 uint32_t rt = GetRtField(instr); |
| 540 return opcode == POP30 && rs != 0 && rs < rt; // && rt != 0 | 540 return opcode == POP30 && rs != 0 && rs < rt; // && rt != 0 |
| 541 } | 541 } |
| 542 | 542 |
| 543 | 543 |
| 544 bool Assembler::IsJicOrJialc(Instr instr) { | |
| 545 uint32_t opcode = GetOpcodeField(instr); | |
| 546 uint32_t rs = GetRsField(instr); | |
| 547 return (opcode == POP66 || opcode == POP76) && rs == 0; | |
| 548 } | |
| 549 | |
| 550 | |
| 544 bool Assembler::IsJump(Instr instr) { | 551 bool Assembler::IsJump(Instr instr) { |
| 545 uint32_t opcode = GetOpcodeField(instr); | 552 uint32_t opcode = GetOpcodeField(instr); |
| 546 uint32_t rt_field = GetRtField(instr); | 553 uint32_t rt_field = GetRtField(instr); |
| 547 uint32_t rd_field = GetRdField(instr); | 554 uint32_t rd_field = GetRdField(instr); |
| 548 uint32_t function_field = GetFunctionField(instr); | 555 uint32_t function_field = GetFunctionField(instr); |
| 549 // Checks if the instruction is a jump. | 556 // Checks if the instruction is a jump. |
| 550 return opcode == J || opcode == JAL || | 557 return opcode == J || opcode == JAL || |
| 551 (opcode == SPECIAL && rt_field == 0 && | 558 (opcode == SPECIAL && rt_field == 0 && |
| 552 ((function_field == JALR) || (rd_field == 0 && (function_field == JR)))); | 559 ((function_field == JALR) || (rd_field == 0 && (function_field == JR)))); |
| 553 } | 560 } |
| 554 | 561 |
| 555 | 562 |
| 563 int16_t Assembler::GetJicOrJialcOffset(Instr instr) { | |
| 564 DCHECK(IsJicOrJialc(instr)); | |
| 565 return instr & kImm16Mask; | |
| 566 } | |
| 567 | |
| 568 | |
| 569 int16_t Assembler::GetLuiOffset(Instr instr) { | |
| 570 DCHECK(IsLui(instr)); | |
| 571 return instr & kImm16Mask; | |
| 572 } | |
| 573 | |
|
balazs.kilvady
2016/01/12 11:30:40
I would add 1 inline function to the header with t
miran.karic
2016/02/18 08:38:04
Acknowledged. There already exists a function GetI
| |
| 574 | |
| 556 bool Assembler::IsJ(Instr instr) { | 575 bool Assembler::IsJ(Instr instr) { |
| 557 uint32_t opcode = GetOpcodeField(instr); | 576 uint32_t opcode = GetOpcodeField(instr); |
| 558 // Checks if the instruction is a jump. | 577 // Checks if the instruction is a jump. |
| 559 return opcode == J; | 578 return opcode == J; |
| 560 } | 579 } |
| 561 | 580 |
| 562 | 581 |
| 563 bool Assembler::IsJal(Instr instr) { | 582 bool Assembler::IsJal(Instr instr) { |
| 564 return GetOpcodeField(instr) == JAL; | 583 return GetOpcodeField(instr) == JAL; |
| 565 } | 584 } |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 697 | 716 |
| 698 if (imm == kEndOfChain) { | 717 if (imm == kEndOfChain) { |
| 699 // EndOfChain sentinel is returned directly, not relative to pc or pos. | 718 // EndOfChain sentinel is returned directly, not relative to pc or pos. |
| 700 return kEndOfChain; | 719 return kEndOfChain; |
| 701 } else { | 720 } else { |
| 702 return pos + Assembler::kBranchPCOffset + imm; | 721 return pos + Assembler::kBranchPCOffset + imm; |
| 703 } | 722 } |
| 704 } | 723 } |
| 705 | 724 |
| 706 | 725 |
| 726 uint32_t Assembler::createTargetAddress(Instr instr_lui, Instr instr_jic) { | |
|
paul.l...
2016/01/11 22:34:57
nit: Start with capital C: CreateTargetAddress, or
miran.karic
2016/02/18 08:38:05
Done.
| |
| 727 DCHECK(IsLui(instr_lui) && IsJicOrJialc(instr_jic)); | |
| 728 int16_t jic_offset = GetJicOrJialcOffset(instr_jic); | |
| 729 int16_t lui_offset = GetLuiOffset(instr_lui); | |
| 730 | |
| 731 | |
| 732 if (jic_offset < 0) { | |
| 733 lui_offset += kImm16Mask; | |
| 734 } | |
| 735 uint32_t lui_offsetU = ((uint32_t)lui_offset) << kLuiShift; | |
|
paul.l...
2016/01/11 22:34:57
nit: probably should not end in 'U', suggest '_u'
miran.karic
2016/02/18 08:38:04
Done.
| |
| 736 uint32_t jic_offsetU = ((uint32_t)jic_offset) & kImm16Mask; | |
| 737 | |
| 738 return lui_offsetU | jic_offsetU; | |
| 739 } | |
| 740 | |
| 741 | |
| 742 // Idea is to use just lui and jic instructions. We will insert lower | |
|
paul.l...
2016/01/11 22:34:57
nit: remove 'Idea is to ', and start with 'Use jus
miran.karic
2016/02/18 08:38:04
Done.
| |
| 743 // part of the target address in jic offset part. Because jic | |
| 744 // sign-extends | |
| 745 // offset and then add it with register, before that addition, | |
| 746 // difference | |
| 747 // between uppert part of the target address and upper part of the | |
| 748 // sign-extended | |
| 749 // offset (0xffff or 0x0000), will be inserted in jic register with lui | |
| 750 // instruction. | |
| 751 | |
| 752 | |
| 753 void Assembler::unpackTargetAddress(uint32_t address, int16_t& lui_offset, | |
| 754 int16_t& jic_offset) { | |
| 755 lui_offset = (address & kHiMask) >> kLuiShift; | |
| 756 jic_offset = address & kLoMask; | |
| 757 | |
| 758 if (jic_offset < 0) { | |
| 759 lui_offset -= kImm16Mask; | |
| 760 } | |
| 761 } | |
| 762 | |
| 763 | |
| 764 void Assembler::unpackTargetAddressUnsigned(uint32_t address, | |
| 765 uint32_t& lui_offset, | |
| 766 uint32_t& jic_offset) { | |
| 767 int16_t lui_offset16 = (address & kHiMask) >> kLuiShift; | |
| 768 int16_t jic_offset16 = address & kLoMask; | |
| 769 | |
| 770 if (jic_offset16 < 0) { | |
| 771 lui_offset16 -= kImm16Mask; | |
| 772 } | |
| 773 lui_offset = ((uint32_t)lui_offset16) & kImm16Mask; | |
| 774 jic_offset = ((uint32_t)jic_offset16) & kImm16Mask; | |
| 775 } | |
| 776 | |
| 777 | |
| 707 int Assembler::target_at(int pos, bool is_internal) { | 778 int Assembler::target_at(int pos, bool is_internal) { |
| 708 Instr instr = instr_at(pos); | 779 Instr instr = instr_at(pos); |
| 709 if (is_internal) { | 780 if (is_internal) { |
| 710 if (instr == 0) { | 781 if (instr == 0) { |
| 711 return kEndOfChain; | 782 return kEndOfChain; |
| 712 } else { | 783 } else { |
| 713 int32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos); | 784 int32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos); |
| 714 int delta = static_cast<int>(instr_address - instr); | 785 int delta = static_cast<int>(instr_address - instr); |
| 715 DCHECK(pos > delta); | 786 DCHECK(pos > delta); |
| 716 return pos - delta; | 787 return pos - delta; |
| 717 } | 788 } |
| 718 } | 789 } |
| 719 if ((instr & ~kImm16Mask) == 0) { | 790 if ((instr & ~kImm16Mask) == 0) { |
| 720 // Emitted label constant, not part of a branch. | 791 // Emitted label constant, not part of a branch. |
| 721 if (instr == 0) { | 792 if (instr == 0) { |
| 722 return kEndOfChain; | 793 return kEndOfChain; |
| 723 } else { | 794 } else { |
| 724 int32_t imm18 =((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14; | 795 int32_t imm18 =((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14; |
| 725 return (imm18 + pos); | 796 return (imm18 + pos); |
| 726 } | 797 } |
| 727 } | 798 } |
| 728 // Check we have a branch or jump instruction. | 799 // Check we have a branch or jump instruction. |
| 729 DCHECK(IsBranch(instr) || IsLui(instr)); | 800 DCHECK(IsBranch(instr) || IsLui(instr) || IsJicOrJialc(instr)); |
|
balazs.kilvady
2016/01/12 11:30:40
It looks like In the bellow code block that only i
miran.karic
2016/02/18 08:38:04
Acknowledged. At first I thought you are referring
| |
| 730 if (IsBranch(instr)) { | 801 if (IsBranch(instr)) { |
| 731 return AddBranchOffset(pos, instr); | 802 return AddBranchOffset(pos, instr); |
| 732 } else { | 803 } else { |
| 733 Instr instr_lui = instr_at(pos + 0 * Assembler::kInstrSize); | 804 Instr instr1 = instr_at(pos + 0 * Assembler::kInstrSize); |
| 734 Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize); | 805 Instr instr2 = instr_at(pos + 1 * Assembler::kInstrSize); |
| 735 DCHECK(IsOri(instr_ori)); | 806 DCHECK(IsOri(instr2) || IsJicOrJialc(instr2)); |
| 736 int32_t imm = (instr_lui & static_cast<int32_t>(kImm16Mask)) << kLuiShift; | 807 int32_t imm; |
| 737 imm |= (instr_ori & static_cast<int32_t>(kImm16Mask)); | 808 if (IsJicOrJialc(instr2)) { |
| 809 imm = createTargetAddress(instr1, instr2); | |
| 810 } else { | |
| 811 imm = (instr1 & static_cast<int32_t>(kImm16Mask)) << kLuiShift; | |
| 812 imm |= (instr2 & static_cast<int32_t>(kImm16Mask)); | |
| 813 } | |
| 738 | 814 |
| 739 if (imm == kEndOfJumpChain) { | 815 if (imm == kEndOfJumpChain) { |
| 740 // EndOfChain sentinel is returned directly, not relative to pc or pos. | 816 // EndOfChain sentinel is returned directly, not relative to pc or pos. |
| 741 return kEndOfChain; | 817 return kEndOfChain; |
| 742 } else { | 818 } else { |
| 743 uint32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos); | 819 uint32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos); |
| 744 int32_t delta = instr_address - imm; | 820 int32_t delta = instr_address - imm; |
| 745 DCHECK(pos > delta); | 821 DCHECK(pos > delta); |
| 746 return pos - delta; | 822 return pos - delta; |
| 747 } | 823 } |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 775 return; | 851 return; |
| 776 } | 852 } |
| 777 if ((instr & ~kImm16Mask) == 0) { | 853 if ((instr & ~kImm16Mask) == 0) { |
| 778 DCHECK(target_pos == kEndOfChain || target_pos >= 0); | 854 DCHECK(target_pos == kEndOfChain || target_pos >= 0); |
| 779 // Emitted label constant, not part of a branch. | 855 // Emitted label constant, not part of a branch. |
| 780 // Make label relative to Code* of generated Code object. | 856 // Make label relative to Code* of generated Code object. |
| 781 instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag)); | 857 instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag)); |
| 782 return; | 858 return; |
| 783 } | 859 } |
| 784 | 860 |
| 785 DCHECK(IsBranch(instr) || IsLui(instr)); | 861 DCHECK(IsBranch(instr) || IsLui(instr) || IsJicOrJialc(instr)); |
|
balazs.kilvady
2016/01/12 11:30:40
Like at the previous DCHECK() comment.
miran.karic
2016/02/18 08:38:04
Done.
| |
| 786 if (IsBranch(instr)) { | 862 if (IsBranch(instr)) { |
| 787 instr = SetBranchOffset(pos, target_pos, instr); | 863 instr = SetBranchOffset(pos, target_pos, instr); |
| 788 instr_at_put(pos, instr); | 864 instr_at_put(pos, instr); |
| 789 } else { | 865 } else { |
| 790 Instr instr_lui = instr_at(pos + 0 * Assembler::kInstrSize); | 866 Instr instr1 = instr_at(pos + 0 * Assembler::kInstrSize); |
| 791 Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize); | 867 Instr instr2 = instr_at(pos + 1 * Assembler::kInstrSize); |
| 792 DCHECK(IsOri(instr_ori)); | 868 DCHECK(IsOri(instr2) || IsJicOrJialc(instr2)); |
| 793 uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos; | 869 uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos; |
| 794 DCHECK((imm & 3) == 0); | 870 DCHECK((imm & 3) == 0); |
| 795 | 871 DCHECK(IsLui(instr1) && (IsJicOrJialc(instr2) || IsOri(instr2))); |
| 796 instr_lui &= ~kImm16Mask; | 872 if (IsJicOrJialc(instr2)) { |
|
paul.l...
2016/01/11 22:34:57
Just for readability, can this if (IsJicOrJialc(in
miran.karic
2016/02/18 08:38:04
Done.
| |
| 797 instr_ori &= ~kImm16Mask; | 873 uint32_t lui_offsetU, jic_offsetU; |
|
paul.l...
2016/01/11 22:34:57
nit: as before, don't use capital U at end like th
miran.karic
2016/02/18 08:38:04
Done.
| |
| 798 | 874 unpackTargetAddressUnsigned(imm, lui_offsetU, jic_offsetU); |
| 799 instr_at_put(pos + 0 * Assembler::kInstrSize, | 875 } |
| 800 instr_lui | ((imm & kHiMask) >> kLuiShift)); | 876 instr1 &= ~kImm16Mask; |
| 801 instr_at_put(pos + 1 * Assembler::kInstrSize, | 877 instr2 &= ~kImm16Mask; |
| 802 instr_ori | (imm & kImm16Mask)); | 878 if (IsJicOrJialc(instr2)) { |
| 879 uint32_t lui_offsetU, jic_offsetU; | |
| 880 unpackTargetAddressUnsigned(imm, lui_offsetU, jic_offsetU); | |
| 881 instr_at_put(pos + 0 * Assembler::kInstrSize, instr1 | lui_offsetU); | |
| 882 instr_at_put(pos + 1 * Assembler::kInstrSize, instr2 | jic_offsetU); | |
| 883 } else { | |
| 884 instr_at_put(pos + 0 * Assembler::kInstrSize, | |
| 885 instr1 | ((imm & kHiMask) >> kLuiShift)); | |
| 886 instr_at_put(pos + 1 * Assembler::kInstrSize, | |
| 887 instr2 | (imm & kImm16Mask)); | |
| 888 } | |
| 803 } | 889 } |
| 804 } | 890 } |
| 805 | 891 |
| 806 | 892 |
| 807 void Assembler::print(Label* L) { | 893 void Assembler::print(Label* L) { |
| 808 if (L->is_unused()) { | 894 if (L->is_unused()) { |
| 809 PrintF("unused label\n"); | 895 PrintF("unused label\n"); |
| 810 } else if (L->is_bound()) { | 896 } else if (L->is_bound()) { |
| 811 PrintF("bound label to %d\n", L->pos()); | 897 PrintF("bound label to %d\n", L->pos()); |
| 812 } else if (L->is_linked()) { | 898 } else if (L->is_linked()) { |
| (...skipping 1970 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2783 if (RelocInfo::IsInternalReference(rmode)) { | 2869 if (RelocInfo::IsInternalReference(rmode)) { |
| 2784 int32_t* p = reinterpret_cast<int32_t*>(pc); | 2870 int32_t* p = reinterpret_cast<int32_t*>(pc); |
| 2785 if (*p == 0) { | 2871 if (*p == 0) { |
| 2786 return 0; // Number of instructions patched. | 2872 return 0; // Number of instructions patched. |
| 2787 } | 2873 } |
| 2788 *p += pc_delta; | 2874 *p += pc_delta; |
| 2789 return 1; // Number of instructions patched. | 2875 return 1; // Number of instructions patched. |
| 2790 } else { | 2876 } else { |
| 2791 DCHECK(RelocInfo::IsInternalReferenceEncoded(rmode)); | 2877 DCHECK(RelocInfo::IsInternalReferenceEncoded(rmode)); |
| 2792 if (IsLui(instr)) { | 2878 if (IsLui(instr)) { |
| 2793 Instr instr_lui = instr_at(pc + 0 * Assembler::kInstrSize); | 2879 Instr instr1 = instr_at(pc + 0 * Assembler::kInstrSize); |
| 2794 Instr instr_ori = instr_at(pc + 1 * Assembler::kInstrSize); | 2880 Instr instr2 = instr_at(pc + 1 * Assembler::kInstrSize); |
| 2795 DCHECK(IsOri(instr_ori)); | 2881 DCHECK(IsOri(instr2) || IsJicOrJialc(instr2)); |
| 2796 int32_t imm = (instr_lui & static_cast<int32_t>(kImm16Mask)) << kLuiShift; | 2882 int32_t imm; |
| 2797 imm |= (instr_ori & static_cast<int32_t>(kImm16Mask)); | 2883 if (IsJicOrJialc(instr2)) { |
| 2884 imm = createTargetAddress(instr1, instr2); | |
| 2885 } else { | |
| 2886 imm = (instr1 & static_cast<int32_t>(kImm16Mask)) << kLuiShift; | |
| 2887 imm |= (instr2 & static_cast<int32_t>(kImm16Mask)); | |
| 2888 } | |
| 2889 | |
| 2798 if (imm == kEndOfJumpChain) { | 2890 if (imm == kEndOfJumpChain) { |
| 2799 return 0; // Number of instructions patched. | 2891 return 0; // Number of instructions patched. |
| 2800 } | 2892 } |
| 2801 imm += pc_delta; | 2893 imm += pc_delta; |
| 2802 DCHECK((imm & 3) == 0); | 2894 DCHECK((imm & 3) == 0); |
| 2803 | 2895 |
| 2804 instr_lui &= ~kImm16Mask; | 2896 instr1 &= ~kImm16Mask; |
| 2805 instr_ori &= ~kImm16Mask; | 2897 instr2 &= ~kImm16Mask; |
| 2806 | 2898 |
| 2807 instr_at_put(pc + 0 * Assembler::kInstrSize, | 2899 if (IsJicOrJialc(instr2)) { |
| 2808 instr_lui | ((imm >> kLuiShift) & kImm16Mask)); | 2900 uint32_t lui_offsetU, jic_offsetU; |
| 2809 instr_at_put(pc + 1 * Assembler::kInstrSize, | 2901 Assembler::unpackTargetAddressUnsigned(imm, lui_offsetU, jic_offsetU); |
| 2810 instr_ori | (imm & kImm16Mask)); | 2902 instr_at_put(pc + 0 * Assembler::kInstrSize, instr1 | lui_offsetU); |
| 2903 instr_at_put(pc + 1 * Assembler::kInstrSize, instr2 | jic_offsetU); | |
| 2904 } else { | |
| 2905 instr_at_put(pc + 0 * Assembler::kInstrSize, | |
| 2906 instr1 | ((imm >> kLuiShift) & kImm16Mask)); | |
| 2907 instr_at_put(pc + 1 * Assembler::kInstrSize, | |
| 2908 instr2 | (imm & kImm16Mask)); | |
| 2909 } | |
| 2811 return 2; // Number of instructions patched. | 2910 return 2; // Number of instructions patched. |
| 2812 } else { | 2911 } else { |
| 2813 UNREACHABLE(); | 2912 UNREACHABLE(); |
| 2814 return 0; | 2913 return 0; |
| 2815 } | 2914 } |
| 2816 } | 2915 } |
| 2817 } | 2916 } |
| 2818 | 2917 |
| 2819 | 2918 |
| 2820 void Assembler::GrowBuffer() { | 2919 void Assembler::GrowBuffer() { |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2969 { BlockTrampolinePoolScope block_trampoline_pool(this); | 3068 { BlockTrampolinePoolScope block_trampoline_pool(this); |
| 2970 Label after_pool; | 3069 Label after_pool; |
| 2971 if (IsMipsArchVariant(kMips32r6)) { | 3070 if (IsMipsArchVariant(kMips32r6)) { |
| 2972 bc(&after_pool); | 3071 bc(&after_pool); |
| 2973 } else { | 3072 } else { |
| 2974 b(&after_pool); | 3073 b(&after_pool); |
| 2975 nop(); | 3074 nop(); |
| 2976 } | 3075 } |
| 2977 | 3076 |
| 2978 int pool_start = pc_offset(); | 3077 int pool_start = pc_offset(); |
| 2979 for (int i = 0; i < unbound_labels_count_; i++) { | 3078 if (IsMipsArchVariant(kMips32r6)) { |
| 2980 uint32_t imm32; | 3079 for (int i = 0; i < unbound_labels_count_; i++) { |
| 2981 imm32 = jump_address(&after_pool); | 3080 uint32_t imm32; |
| 2982 { BlockGrowBufferScope block_buf_growth(this); | 3081 imm32 = jump_address(&after_pool); |
| 2983 // Buffer growth (and relocation) must be blocked for internal | 3082 uint32_t lui_offset, jic_offset; |
| 2984 // references until associated instructions are emitted and available | 3083 unpackTargetAddressUnsigned(imm32, lui_offset, jic_offset); |
| 2985 // to be patched. | 3084 { |
| 2986 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE_ENCODED); | 3085 BlockGrowBufferScope block_buf_growth(this); |
| 2987 lui(at, (imm32 & kHiMask) >> kLuiShift); | 3086 // Buffer growth (and relocation) must be blocked for internal |
| 2988 ori(at, at, (imm32 & kImm16Mask)); | 3087 // references until associated instructions are emitted and |
| 3088 // available to be patched. | |
| 3089 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE_ENCODED); | |
| 3090 lui(at, lui_offset); | |
| 3091 jic(at, jic_offset); | |
| 3092 } | |
| 3093 CheckBuffer(); | |
| 2989 } | 3094 } |
| 2990 jr(at); | 3095 } else { |
| 2991 nop(); | 3096 for (int i = 0; i < unbound_labels_count_; i++) { |
| 3097 uint32_t imm32; | |
| 3098 imm32 = jump_address(&after_pool); | |
| 3099 { | |
| 3100 BlockGrowBufferScope block_buf_growth(this); | |
| 3101 // Buffer growth (and relocation) must be blocked for internal | |
| 3102 // references until associated instructions are emitted and | |
| 3103 // available to be patched. | |
| 3104 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE_ENCODED); | |
| 3105 lui(at, (imm32 & kHiMask) >> kLuiShift); | |
| 3106 ori(at, at, (imm32 & kImm16Mask)); | |
| 3107 } | |
| 3108 CheckBuffer(); | |
| 3109 jr(at); | |
| 3110 nop(); | |
| 3111 } | |
| 2992 } | 3112 } |
| 2993 bind(&after_pool); | 3113 bind(&after_pool); |
| 2994 trampoline_ = Trampoline(pool_start, unbound_labels_count_); | 3114 trampoline_ = Trampoline(pool_start, unbound_labels_count_); |
| 2995 | 3115 |
| 2996 trampoline_emitted_ = true; | 3116 trampoline_emitted_ = true; |
| 2997 // As we are only going to emit trampoline once, we need to prevent any | 3117 // As we are only going to emit trampoline once, we need to prevent any |
| 2998 // further emission. | 3118 // further emission. |
| 2999 next_buffer_check_ = kMaxInt; | 3119 next_buffer_check_ = kMaxInt; |
| 3000 } | 3120 } |
| 3001 } else { | 3121 } else { |
| 3002 // Number of branches to unbound label at this point is zero, so we can | 3122 // Number of branches to unbound label at this point is zero, so we can |
| 3003 // move next buffer check to maximum. | 3123 // move next buffer check to maximum. |
| 3004 next_buffer_check_ = pc_offset() + | 3124 next_buffer_check_ = pc_offset() + |
| 3005 kMaxBranchOffset - kTrampolineSlotsSize * 16; | 3125 kMaxBranchOffset - kTrampolineSlotsSize * 16; |
| 3006 } | 3126 } |
| 3007 return; | 3127 return; |
| 3008 } | 3128 } |
| 3009 | 3129 |
| 3010 | 3130 |
| 3011 Address Assembler::target_address_at(Address pc) { | 3131 Address Assembler::target_address_at(Address pc) { |
| 3012 Instr instr1 = instr_at(pc); | 3132 Instr instr1 = instr_at(pc); |
| 3013 Instr instr2 = instr_at(pc + kInstrSize); | 3133 Instr instr2 = instr_at(pc + kInstrSize); |
| 3014 // Interpret 2 instructions generated by li: lui/ori | 3134 // Interpret 2 instructions generated by li: lui/ori |
| 3015 if ((GetOpcodeField(instr1) == LUI) && (GetOpcodeField(instr2) == ORI)) { | 3135 if (IsLui(instr1) && IsOri(instr2)) { |
| 3016 // Assemble the 32 bit value. | 3136 // Assemble the 32 bit value. |
| 3017 return reinterpret_cast<Address>( | 3137 return reinterpret_cast<Address>((GetImmediate16(instr1) << kLuiShift) | |
| 3018 (GetImmediate16(instr1) << 16) | GetImmediate16(instr2)); | 3138 GetImmediate16(instr2)); |
| 3019 } | 3139 } |
| 3020 | 3140 |
| 3021 // We should never get here, force a bad address if we do. | 3141 // We should never get here, force a bad address if we do. |
| 3022 UNREACHABLE(); | 3142 UNREACHABLE(); |
| 3023 return (Address)0x0; | 3143 return (Address)0x0; |
| 3024 } | 3144 } |
| 3025 | 3145 |
| 3026 | 3146 |
| 3027 // MIPS and ia32 use opposite encoding for qNaN and sNaN, such that ia32 | 3147 // MIPS and ia32 use opposite encoding for qNaN and sNaN, such that ia32 |
| 3028 // qNaN is a MIPS sNaN, and ia32 sNaN is MIPS qNaN. If running from a heap | 3148 // qNaN is a MIPS sNaN, and ia32 sNaN is MIPS qNaN. If running from a heap |
| 3029 // snapshot generated on ia32, the resulting MIPS sNaN must be quieted. | 3149 // snapshot generated on ia32, the resulting MIPS sNaN must be quieted. |
| 3030 // OS::nan_value() returns a qNaN. | 3150 // OS::nan_value() returns a qNaN. |
| 3031 void Assembler::QuietNaN(HeapObject* object) { | 3151 void Assembler::QuietNaN(HeapObject* object) { |
| 3032 HeapNumber::cast(object)->set_value(std::numeric_limits<double>::quiet_NaN()); | 3152 HeapNumber::cast(object)->set_value(std::numeric_limits<double>::quiet_NaN()); |
| 3033 } | 3153 } |
| 3034 | 3154 |
| 3035 | 3155 |
| 3036 // On Mips, a target address is stored in a lui/ori instruction pair, each | 3156 // On Mips, a target address is stored in a lui/ori instruction pair, each |
| 3037 // of which load 16 bits of the 32-bit address to a register. | 3157 // of which load 16 bits of the 32-bit address to a register. |
| 3038 // Patching the address must replace both instr, and flush the i-cache. | 3158 // Patching the address must replace both instr, and flush the i-cache. |
| 3159 // On r6, target address is stored in a lui/jic pair, and both instr have to be | |
| 3160 // patched. | |
| 3039 // | 3161 // |
| 3040 // There is an optimization below, which emits a nop when the address | 3162 // There is an optimization below, which emits a nop when the address |
| 3041 // fits in just 16 bits. This is unlikely to help, and should be benchmarked, | 3163 // fits in just 16 bits. This is unlikely to help, and should be benchmarked, |
| 3042 // and possibly removed. | 3164 // and possibly removed. |
| 3043 void Assembler::set_target_address_at(Isolate* isolate, Address pc, | 3165 void Assembler::set_target_address_at(Isolate* isolate, Address pc, |
| 3044 Address target, | 3166 Address target, |
| 3045 ICacheFlushMode icache_flush_mode) { | 3167 ICacheFlushMode icache_flush_mode) { |
| 3046 Instr instr2 = instr_at(pc + kInstrSize); | 3168 Instr instr2 = instr_at(pc + kInstrSize); |
| 3047 uint32_t rt_code = GetRtField(instr2); | 3169 uint32_t rt_code = GetRtField(instr2); |
| 3048 uint32_t* p = reinterpret_cast<uint32_t*>(pc); | 3170 uint32_t* p = reinterpret_cast<uint32_t*>(pc); |
| 3049 uint32_t itarget = reinterpret_cast<uint32_t>(target); | 3171 uint32_t itarget = reinterpret_cast<uint32_t>(target); |
| 3050 | 3172 |
| 3051 #ifdef DEBUG | 3173 #ifdef DEBUG |
| 3052 // Check we have the result from a li macro-instruction, using instr pair. | 3174 // Check we have the result from a li macro-instruction, using instr pair. |
| 3053 Instr instr1 = instr_at(pc); | 3175 Instr instr1 = instr_at(pc); |
| 3054 CHECK((GetOpcodeField(instr1) == LUI && GetOpcodeField(instr2) == ORI)); | 3176 CHECK(IsLui(instr1) && (IsOri(instr2) || IsJicOrJialc(instr2))); |
| 3055 #endif | 3177 #endif |
| 3056 | 3178 |
| 3057 // Must use 2 instructions to insure patchable code => just use lui and ori. | 3179 if (IsJicOrJialc(instr2)) { |
| 3058 // lui rt, upper-16. | 3180 // Must use 2 instructions to insure patchable code => use lui and jic |
| 3059 // ori rt rt, lower-16. | 3181 uint32_t lui_offset, jic_offset; |
| 3060 *p = LUI | rt_code | ((itarget & kHiMask) >> kLuiShift); | 3182 Assembler::unpackTargetAddressUnsigned(itarget, lui_offset, jic_offset); |
| 3061 *(p + 1) = ORI | rt_code | (rt_code << 5) | (itarget & kImm16Mask); | |
| 3062 | 3183 |
| 3184 *p &= ~kImm16Mask; | |
| 3185 *(p + 1) &= ~kImm16Mask; | |
| 3186 | |
| 3187 *p |= lui_offset; | |
| 3188 *(p + 1) |= jic_offset; | |
| 3189 | |
| 3190 } else { | |
| 3191 // Must use 2 instructions to insure patchable code => just use lui and ori. | |
| 3192 // lui rt, upper-16. | |
| 3193 // ori rt rt, lower-16. | |
| 3194 *p = LUI | rt_code | ((itarget & kHiMask) >> kLuiShift); | |
| 3195 *(p + 1) = ORI | rt_code | (rt_code << 5) | (itarget & kImm16Mask); | |
| 3196 } | |
| 3063 | 3197 |
| 3064 if (icache_flush_mode != SKIP_ICACHE_FLUSH) { | 3198 if (icache_flush_mode != SKIP_ICACHE_FLUSH) { |
| 3065 Assembler::FlushICache(isolate, pc, 2 * sizeof(int32_t)); | 3199 Assembler::FlushICache(isolate, pc, 2 * sizeof(int32_t)); |
| 3066 } | 3200 } |
| 3067 } | 3201 } |
| 3068 | 3202 |
| 3069 } // namespace internal | 3203 } // namespace internal |
| 3070 } // namespace v8 | 3204 } // namespace v8 |
| 3071 | 3205 |
| 3072 #endif // V8_TARGET_ARCH_MIPS | 3206 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |