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 516 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 527 } | 527 } |
| 528 | 528 |
| 529 | 529 |
| 530 bool Assembler::IsBnec(Instr instr) { | 530 bool Assembler::IsBnec(Instr instr) { |
| 531 uint32_t opcode = GetOpcodeField(instr); | 531 uint32_t opcode = GetOpcodeField(instr); |
| 532 uint32_t rs = GetRsField(instr); | 532 uint32_t rs = GetRsField(instr); |
| 533 uint32_t rt = GetRtField(instr); | 533 uint32_t rt = GetRtField(instr); |
| 534 return opcode == POP30 && rs != 0 && rs < rt; // && rt != 0 | 534 return opcode == POP30 && rs != 0 && rs < rt; // && rt != 0 |
| 535 } | 535 } |
| 536 | 536 |
| 537 bool Assembler::IsJicOrJialc(Instr instr) { | |
| 538 uint32_t opcode = GetOpcodeField(instr); | |
| 539 uint32_t rs = GetRsField(instr); | |
| 540 return (opcode == POP66 || opcode == POP76) && rs == 0; | |
| 541 } | |
| 537 | 542 |
| 538 bool Assembler::IsJump(Instr instr) { | 543 bool Assembler::IsJump(Instr instr) { |
| 539 uint32_t opcode = GetOpcodeField(instr); | 544 uint32_t opcode = GetOpcodeField(instr); |
| 540 uint32_t rt_field = GetRtField(instr); | 545 uint32_t rt_field = GetRtField(instr); |
| 541 uint32_t rd_field = GetRdField(instr); | 546 uint32_t rd_field = GetRdField(instr); |
| 542 uint32_t function_field = GetFunctionField(instr); | 547 uint32_t function_field = GetFunctionField(instr); |
| 543 // Checks if the instruction is a jump. | 548 // Checks if the instruction is a jump. |
| 544 return opcode == J || opcode == JAL || | 549 return opcode == J || opcode == JAL || |
| 545 (opcode == SPECIAL && rt_field == 0 && | 550 (opcode == SPECIAL && rt_field == 0 && |
| 546 ((function_field == JALR) || (rd_field == 0 && (function_field == JR)))); | 551 ((function_field == JALR) || (rd_field == 0 && (function_field == JR)))); |
| 547 } | 552 } |
| 548 | 553 |
| 554 int16_t Assembler::GetJicOrJialcOffset(Instr instr) { | |
| 555 DCHECK(IsJicOrJialc(instr)); | |
| 556 return instr & kImm16Mask; | |
| 557 } | |
| 558 | |
| 559 int16_t Assembler::GetLuiOffset(Instr instr) { | |
| 560 DCHECK(IsLui(instr)); | |
| 561 return instr & kImm16Mask; | |
| 562 } | |
| 549 | 563 |
| 550 bool Assembler::IsJ(Instr instr) { | 564 bool Assembler::IsJ(Instr instr) { |
| 551 uint32_t opcode = GetOpcodeField(instr); | 565 uint32_t opcode = GetOpcodeField(instr); |
| 552 // Checks if the instruction is a jump. | 566 // Checks if the instruction is a jump. |
| 553 return opcode == J; | 567 return opcode == J; |
| 554 } | 568 } |
| 555 | 569 |
| 556 | 570 |
| 557 bool Assembler::IsJal(Instr instr) { | 571 bool Assembler::IsJal(Instr instr) { |
| 558 return GetOpcodeField(instr) == JAL; | 572 return GetOpcodeField(instr) == JAL; |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 690 int32_t imm = ((instr & mask) << bits) >> (bits - 2); | 704 int32_t imm = ((instr & mask) << bits) >> (bits - 2); |
| 691 | 705 |
| 692 if (imm == kEndOfChain) { | 706 if (imm == kEndOfChain) { |
| 693 // EndOfChain sentinel is returned directly, not relative to pc or pos. | 707 // EndOfChain sentinel is returned directly, not relative to pc or pos. |
| 694 return kEndOfChain; | 708 return kEndOfChain; |
| 695 } else { | 709 } else { |
| 696 return pos + Assembler::kBranchPCOffset + imm; | 710 return pos + Assembler::kBranchPCOffset + imm; |
| 697 } | 711 } |
| 698 } | 712 } |
| 699 | 713 |
| 714 uint32_t Assembler::CreateTargetAddress(Instr instr_lui, Instr instr_jic) { | |
| 715 DCHECK(IsLui(instr_lui) && IsJicOrJialc(instr_jic)); | |
| 716 int16_t jic_offset = GetJicOrJialcOffset(instr_jic); | |
| 717 int16_t lui_offset = GetLuiOffset(instr_lui); | |
| 718 | |
| 719 if (jic_offset < 0) { | |
| 720 lui_offset += kImm16Mask; | |
| 721 } | |
| 722 uint32_t lui_offset_u = ((uint32_t)lui_offset) << kLuiShift; | |
| 723 uint32_t jic_offset_u = ((uint32_t)jic_offset) & kImm16Mask; | |
|
balazs.kilvady
2016/02/19 12:37:40
Please use static_cast<uint32_t>(*_offset) in the
miran.karic
2016/02/19 15:06:51
Done.
| |
| 724 | |
| 725 return lui_offset_u | jic_offset_u; | |
| 726 } | |
| 727 | |
| 728 // Use just lui and jic instructions. Insert lower part of the target address in | |
| 729 // jic offset part. Since jic sign-extends offset and then add it with register, | |
| 730 // before that addition, difference between upper part of the target address and | |
| 731 // upper part of the sign-extended offset (0xffff or 0x0000), will be inserted | |
| 732 // in jic register with lui instruction. | |
| 733 void Assembler::UnpackTargetAddress(uint32_t address, int16_t& lui_offset, | |
| 734 int16_t& jic_offset) { | |
| 735 lui_offset = (address & kHiMask) >> kLuiShift; | |
| 736 jic_offset = address & kLoMask; | |
| 737 | |
| 738 if (jic_offset < 0) { | |
| 739 lui_offset -= kImm16Mask; | |
| 740 } | |
| 741 } | |
| 742 | |
| 743 void Assembler::UnpackTargetAddressUnsigned(uint32_t address, | |
| 744 uint32_t& lui_offset, | |
| 745 uint32_t& jic_offset) { | |
| 746 int16_t lui_offset16 = (address & kHiMask) >> kLuiShift; | |
| 747 int16_t jic_offset16 = address & kLoMask; | |
| 748 | |
| 749 if (jic_offset16 < 0) { | |
| 750 lui_offset16 -= kImm16Mask; | |
| 751 } | |
| 752 lui_offset = ((uint32_t)lui_offset16) & kImm16Mask; | |
| 753 jic_offset = ((uint32_t)jic_offset16) & kImm16Mask; | |
|
balazs.kilvady
2016/02/19 12:37:40
Please use static_cast<uint32_t>(*_offset) in the
miran.karic
2016/02/19 15:06:51
Done.
| |
| 754 } | |
| 700 | 755 |
| 701 int Assembler::target_at(int pos, bool is_internal) { | 756 int Assembler::target_at(int pos, bool is_internal) { |
| 702 Instr instr = instr_at(pos); | 757 Instr instr = instr_at(pos); |
| 703 if (is_internal) { | 758 if (is_internal) { |
| 704 if (instr == 0) { | 759 if (instr == 0) { |
| 705 return kEndOfChain; | 760 return kEndOfChain; |
| 706 } else { | 761 } else { |
| 707 int32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos); | 762 int32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos); |
| 708 int delta = static_cast<int>(instr_address - instr); | 763 int delta = static_cast<int>(instr_address - instr); |
| 709 DCHECK(pos > delta); | 764 DCHECK(pos > delta); |
| 710 return pos - delta; | 765 return pos - delta; |
| 711 } | 766 } |
| 712 } | 767 } |
| 713 if ((instr & ~kImm16Mask) == 0) { | 768 if ((instr & ~kImm16Mask) == 0) { |
| 714 // Emitted label constant, not part of a branch. | 769 // Emitted label constant, not part of a branch. |
| 715 if (instr == 0) { | 770 if (instr == 0) { |
| 716 return kEndOfChain; | 771 return kEndOfChain; |
| 717 } else { | 772 } else { |
| 718 int32_t imm18 =((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14; | 773 int32_t imm18 =((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14; |
| 719 return (imm18 + pos); | 774 return (imm18 + pos); |
| 720 } | 775 } |
| 721 } | 776 } |
| 722 // Check we have a branch or jump instruction. | 777 // Check we have a branch or jump instruction. |
| 723 DCHECK(IsBranch(instr) || IsLui(instr)); | 778 DCHECK(IsBranch(instr) || IsLui(instr) || IsJicOrJialc(instr)); |
|
balazs.kilvady
2016/02/19 12:37:40
It looks like from the bellow code block that only
miran.karic
2016/02/19 15:06:51
Done.
| |
| 724 if (IsBranch(instr)) { | 779 if (IsBranch(instr)) { |
| 725 return AddBranchOffset(pos, instr); | 780 return AddBranchOffset(pos, instr); |
| 726 } else { | 781 } else { |
| 727 Instr instr_lui = instr_at(pos + 0 * Assembler::kInstrSize); | 782 Instr instr1 = instr_at(pos + 0 * Assembler::kInstrSize); |
| 728 Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize); | 783 Instr instr2 = instr_at(pos + 1 * Assembler::kInstrSize); |
| 729 DCHECK(IsOri(instr_ori)); | 784 DCHECK(IsOri(instr2) || IsJicOrJialc(instr2)); |
| 730 int32_t imm = (instr_lui & static_cast<int32_t>(kImm16Mask)) << kLuiShift; | 785 int32_t imm; |
| 731 imm |= (instr_ori & static_cast<int32_t>(kImm16Mask)); | 786 if (IsJicOrJialc(instr2)) { |
| 787 imm = CreateTargetAddress(instr1, instr2); | |
| 788 } else { | |
| 789 imm = (instr1 & static_cast<int32_t>(kImm16Mask)) << kLuiShift; | |
| 790 imm |= (instr2 & static_cast<int32_t>(kImm16Mask)); | |
| 791 } | |
| 732 | 792 |
| 733 if (imm == kEndOfJumpChain) { | 793 if (imm == kEndOfJumpChain) { |
| 734 // EndOfChain sentinel is returned directly, not relative to pc or pos. | 794 // EndOfChain sentinel is returned directly, not relative to pc or pos. |
| 735 return kEndOfChain; | 795 return kEndOfChain; |
| 736 } else { | 796 } else { |
| 737 uint32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos); | 797 uint32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos); |
| 738 int32_t delta = instr_address - imm; | 798 int32_t delta = instr_address - imm; |
| 739 DCHECK(pos > delta); | 799 DCHECK(pos > delta); |
| 740 return pos - delta; | 800 return pos - delta; |
| 741 } | 801 } |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 774 // Make label relative to Code* of generated Code object. | 834 // Make label relative to Code* of generated Code object. |
| 775 instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag)); | 835 instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag)); |
| 776 return; | 836 return; |
| 777 } | 837 } |
| 778 | 838 |
| 779 DCHECK(IsBranch(instr) || IsLui(instr)); | 839 DCHECK(IsBranch(instr) || IsLui(instr)); |
| 780 if (IsBranch(instr)) { | 840 if (IsBranch(instr)) { |
| 781 instr = SetBranchOffset(pos, target_pos, instr); | 841 instr = SetBranchOffset(pos, target_pos, instr); |
| 782 instr_at_put(pos, instr); | 842 instr_at_put(pos, instr); |
| 783 } else { | 843 } else { |
| 784 Instr instr_lui = instr_at(pos + 0 * Assembler::kInstrSize); | 844 Instr instr1 = instr_at(pos + 0 * Assembler::kInstrSize); |
| 785 Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize); | 845 Instr instr2 = instr_at(pos + 1 * Assembler::kInstrSize); |
| 786 DCHECK(IsOri(instr_ori)); | 846 DCHECK(IsOri(instr2) || IsJicOrJialc(instr2)); |
| 787 uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos; | 847 uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos; |
| 788 DCHECK((imm & 3) == 0); | 848 DCHECK((imm & 3) == 0); |
| 849 DCHECK(IsLui(instr1) && (IsJicOrJialc(instr2) || IsOri(instr2))); | |
| 850 instr1 &= ~kImm16Mask; | |
| 851 instr2 &= ~kImm16Mask; | |
| 789 | 852 |
| 790 instr_lui &= ~kImm16Mask; | 853 if (IsJicOrJialc(instr2)) { |
| 791 instr_ori &= ~kImm16Mask; | 854 uint32_t lui_offset_u, jic_offset_u; |
| 792 | 855 UnpackTargetAddressUnsigned(imm, lui_offset_u, jic_offset_u); |
| 793 instr_at_put(pos + 0 * Assembler::kInstrSize, | 856 instr_at_put(pos + 0 * Assembler::kInstrSize, instr1 | lui_offset_u); |
| 794 instr_lui | ((imm & kHiMask) >> kLuiShift)); | 857 instr_at_put(pos + 1 * Assembler::kInstrSize, instr2 | jic_offset_u); |
| 795 instr_at_put(pos + 1 * Assembler::kInstrSize, | 858 } else { |
| 796 instr_ori | (imm & kImm16Mask)); | 859 instr_at_put(pos + 0 * Assembler::kInstrSize, |
| 860 instr1 | ((imm & kHiMask) >> kLuiShift)); | |
| 861 instr_at_put(pos + 1 * Assembler::kInstrSize, | |
| 862 instr2 | (imm & kImm16Mask)); | |
| 863 } | |
| 797 } | 864 } |
| 798 } | 865 } |
| 799 | 866 |
| 800 | 867 |
| 801 void Assembler::print(Label* L) { | 868 void Assembler::print(Label* L) { |
| 802 if (L->is_unused()) { | 869 if (L->is_unused()) { |
| 803 PrintF("unused label\n"); | 870 PrintF("unused label\n"); |
| 804 } else if (L->is_bound()) { | 871 } else if (L->is_bound()) { |
| 805 PrintF("bound label to %d\n", L->pos()); | 872 PrintF("bound label to %d\n", L->pos()); |
| 806 } else if (L->is_linked()) { | 873 } else if (L->is_linked()) { |
| (...skipping 1976 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2783 if (RelocInfo::IsInternalReference(rmode)) { | 2850 if (RelocInfo::IsInternalReference(rmode)) { |
| 2784 int32_t* p = reinterpret_cast<int32_t*>(pc); | 2851 int32_t* p = reinterpret_cast<int32_t*>(pc); |
| 2785 if (*p == 0) { | 2852 if (*p == 0) { |
| 2786 return 0; // Number of instructions patched. | 2853 return 0; // Number of instructions patched. |
| 2787 } | 2854 } |
| 2788 *p += pc_delta; | 2855 *p += pc_delta; |
| 2789 return 1; // Number of instructions patched. | 2856 return 1; // Number of instructions patched. |
| 2790 } else { | 2857 } else { |
| 2791 DCHECK(RelocInfo::IsInternalReferenceEncoded(rmode)); | 2858 DCHECK(RelocInfo::IsInternalReferenceEncoded(rmode)); |
| 2792 if (IsLui(instr)) { | 2859 if (IsLui(instr)) { |
| 2793 Instr instr_lui = instr_at(pc + 0 * Assembler::kInstrSize); | 2860 Instr instr1 = instr_at(pc + 0 * Assembler::kInstrSize); |
| 2794 Instr instr_ori = instr_at(pc + 1 * Assembler::kInstrSize); | 2861 Instr instr2 = instr_at(pc + 1 * Assembler::kInstrSize); |
| 2795 DCHECK(IsOri(instr_ori)); | 2862 DCHECK(IsOri(instr2) || IsJicOrJialc(instr2)); |
| 2796 int32_t imm = (instr_lui & static_cast<int32_t>(kImm16Mask)) << kLuiShift; | 2863 int32_t imm; |
| 2797 imm |= (instr_ori & static_cast<int32_t>(kImm16Mask)); | 2864 if (IsJicOrJialc(instr2)) { |
| 2865 imm = CreateTargetAddress(instr1, instr2); | |
| 2866 } else { | |
| 2867 imm = (instr1 & static_cast<int32_t>(kImm16Mask)) << kLuiShift; | |
| 2868 imm |= (instr2 & static_cast<int32_t>(kImm16Mask)); | |
| 2869 } | |
| 2870 | |
| 2798 if (imm == kEndOfJumpChain) { | 2871 if (imm == kEndOfJumpChain) { |
| 2799 return 0; // Number of instructions patched. | 2872 return 0; // Number of instructions patched. |
| 2800 } | 2873 } |
| 2801 imm += pc_delta; | 2874 imm += pc_delta; |
| 2802 DCHECK((imm & 3) == 0); | 2875 DCHECK((imm & 3) == 0); |
| 2876 instr1 &= ~kImm16Mask; | |
| 2877 instr2 &= ~kImm16Mask; | |
| 2803 | 2878 |
| 2804 instr_lui &= ~kImm16Mask; | 2879 if (IsJicOrJialc(instr2)) { |
| 2805 instr_ori &= ~kImm16Mask; | 2880 uint32_t lui_offset_u, jic_offset_u; |
| 2806 | 2881 Assembler::UnpackTargetAddressUnsigned(imm, lui_offset_u, jic_offset_u); |
| 2807 instr_at_put(pc + 0 * Assembler::kInstrSize, | 2882 instr_at_put(pc + 0 * Assembler::kInstrSize, instr1 | lui_offset_u); |
| 2808 instr_lui | ((imm >> kLuiShift) & kImm16Mask)); | 2883 instr_at_put(pc + 1 * Assembler::kInstrSize, instr2 | jic_offset_u); |
| 2809 instr_at_put(pc + 1 * Assembler::kInstrSize, | 2884 } else { |
| 2810 instr_ori | (imm & kImm16Mask)); | 2885 instr_at_put(pc + 0 * Assembler::kInstrSize, |
| 2886 instr1 | ((imm >> kLuiShift) & kImm16Mask)); | |
| 2887 instr_at_put(pc + 1 * Assembler::kInstrSize, | |
| 2888 instr2 | (imm & kImm16Mask)); | |
| 2889 } | |
| 2811 return 2; // Number of instructions patched. | 2890 return 2; // Number of instructions patched. |
| 2812 } else { | 2891 } else { |
| 2813 UNREACHABLE(); | 2892 UNREACHABLE(); |
| 2814 return 0; | 2893 return 0; |
| 2815 } | 2894 } |
| 2816 } | 2895 } |
| 2817 } | 2896 } |
| 2818 | 2897 |
| 2819 | 2898 |
| 2820 void Assembler::GrowBuffer() { | 2899 void Assembler::GrowBuffer() { |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2957 { BlockTrampolinePoolScope block_trampoline_pool(this); | 3036 { BlockTrampolinePoolScope block_trampoline_pool(this); |
| 2958 Label after_pool; | 3037 Label after_pool; |
| 2959 if (IsMipsArchVariant(kMips32r6)) { | 3038 if (IsMipsArchVariant(kMips32r6)) { |
| 2960 bc(&after_pool); | 3039 bc(&after_pool); |
| 2961 } else { | 3040 } else { |
| 2962 b(&after_pool); | 3041 b(&after_pool); |
| 2963 nop(); | 3042 nop(); |
| 2964 } | 3043 } |
| 2965 | 3044 |
| 2966 int pool_start = pc_offset(); | 3045 int pool_start = pc_offset(); |
| 2967 for (int i = 0; i < unbound_labels_count_; i++) { | 3046 if (IsMipsArchVariant(kMips32r6)) { |
| 2968 uint32_t imm32; | 3047 for (int i = 0; i < unbound_labels_count_; i++) { |
| 2969 imm32 = jump_address(&after_pool); | 3048 uint32_t imm32; |
| 2970 { BlockGrowBufferScope block_buf_growth(this); | 3049 imm32 = jump_address(&after_pool); |
| 2971 // Buffer growth (and relocation) must be blocked for internal | 3050 uint32_t lui_offset, jic_offset; |
| 2972 // references until associated instructions are emitted and available | 3051 UnpackTargetAddressUnsigned(imm32, lui_offset, jic_offset); |
| 2973 // to be patched. | 3052 { |
| 2974 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE_ENCODED); | 3053 BlockGrowBufferScope block_buf_growth(this); |
| 2975 lui(at, (imm32 & kHiMask) >> kLuiShift); | 3054 // Buffer growth (and relocation) must be blocked for internal |
| 2976 ori(at, at, (imm32 & kImm16Mask)); | 3055 // references until associated instructions are emitted and |
| 3056 // available to be patched. | |
| 3057 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE_ENCODED); | |
| 3058 lui(at, lui_offset); | |
| 3059 jic(at, jic_offset); | |
| 3060 } | |
| 3061 CheckBuffer(); | |
| 2977 } | 3062 } |
| 2978 jr(at); | 3063 } else { |
| 2979 nop(); | 3064 for (int i = 0; i < unbound_labels_count_; i++) { |
| 3065 uint32_t imm32; | |
| 3066 imm32 = jump_address(&after_pool); | |
| 3067 { | |
| 3068 BlockGrowBufferScope block_buf_growth(this); | |
| 3069 // Buffer growth (and relocation) must be blocked for internal | |
| 3070 // references until associated instructions are emitted and | |
| 3071 // available to be patched. | |
| 3072 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE_ENCODED); | |
| 3073 lui(at, (imm32 & kHiMask) >> kLuiShift); | |
| 3074 ori(at, at, (imm32 & kImm16Mask)); | |
| 3075 } | |
| 3076 CheckBuffer(); | |
| 3077 jr(at); | |
| 3078 nop(); | |
| 3079 } | |
| 2980 } | 3080 } |
| 2981 bind(&after_pool); | 3081 bind(&after_pool); |
| 2982 trampoline_ = Trampoline(pool_start, unbound_labels_count_); | 3082 trampoline_ = Trampoline(pool_start, unbound_labels_count_); |
| 2983 | 3083 |
| 2984 trampoline_emitted_ = true; | 3084 trampoline_emitted_ = true; |
| 2985 // As we are only going to emit trampoline once, we need to prevent any | 3085 // As we are only going to emit trampoline once, we need to prevent any |
| 2986 // further emission. | 3086 // further emission. |
| 2987 next_buffer_check_ = kMaxInt; | 3087 next_buffer_check_ = kMaxInt; |
| 2988 } | 3088 } |
| 2989 } else { | 3089 } else { |
| 2990 // Number of branches to unbound label at this point is zero, so we can | 3090 // Number of branches to unbound label at this point is zero, so we can |
| 2991 // move next buffer check to maximum. | 3091 // move next buffer check to maximum. |
| 2992 next_buffer_check_ = pc_offset() + | 3092 next_buffer_check_ = pc_offset() + |
| 2993 kMaxBranchOffset - kTrampolineSlotsSize * 16; | 3093 kMaxBranchOffset - kTrampolineSlotsSize * 16; |
| 2994 } | 3094 } |
| 2995 return; | 3095 return; |
| 2996 } | 3096 } |
| 2997 | 3097 |
| 2998 | 3098 |
| 2999 Address Assembler::target_address_at(Address pc) { | 3099 Address Assembler::target_address_at(Address pc) { |
| 3000 Instr instr1 = instr_at(pc); | 3100 Instr instr1 = instr_at(pc); |
| 3001 Instr instr2 = instr_at(pc + kInstrSize); | 3101 Instr instr2 = instr_at(pc + kInstrSize); |
| 3002 // Interpret 2 instructions generated by li: lui/ori | 3102 // Interpret 2 instructions generated by li: lui/ori |
| 3003 if ((GetOpcodeField(instr1) == LUI) && (GetOpcodeField(instr2) == ORI)) { | 3103 if (IsLui(instr1) && IsOri(instr2)) { |
| 3004 // Assemble the 32 bit value. | 3104 // Assemble the 32 bit value. |
| 3005 return reinterpret_cast<Address>( | 3105 return reinterpret_cast<Address>((GetImmediate16(instr1) << kLuiShift) | |
| 3006 (GetImmediate16(instr1) << 16) | GetImmediate16(instr2)); | 3106 GetImmediate16(instr2)); |
| 3007 } | 3107 } |
| 3008 | 3108 |
| 3009 // We should never get here, force a bad address if we do. | 3109 // We should never get here, force a bad address if we do. |
| 3010 UNREACHABLE(); | 3110 UNREACHABLE(); |
| 3011 return (Address)0x0; | 3111 return (Address)0x0; |
| 3012 } | 3112 } |
| 3013 | 3113 |
| 3014 | 3114 |
| 3015 // MIPS and ia32 use opposite encoding for qNaN and sNaN, such that ia32 | 3115 // MIPS and ia32 use opposite encoding for qNaN and sNaN, such that ia32 |
| 3016 // qNaN is a MIPS sNaN, and ia32 sNaN is MIPS qNaN. If running from a heap | 3116 // qNaN is a MIPS sNaN, and ia32 sNaN is MIPS qNaN. If running from a heap |
| 3017 // snapshot generated on ia32, the resulting MIPS sNaN must be quieted. | 3117 // snapshot generated on ia32, the resulting MIPS sNaN must be quieted. |
| 3018 // OS::nan_value() returns a qNaN. | 3118 // OS::nan_value() returns a qNaN. |
| 3019 void Assembler::QuietNaN(HeapObject* object) { | 3119 void Assembler::QuietNaN(HeapObject* object) { |
| 3020 HeapNumber::cast(object)->set_value(std::numeric_limits<double>::quiet_NaN()); | 3120 HeapNumber::cast(object)->set_value(std::numeric_limits<double>::quiet_NaN()); |
| 3021 } | 3121 } |
| 3022 | 3122 |
| 3023 | 3123 |
| 3024 // On Mips, a target address is stored in a lui/ori instruction pair, each | 3124 // On Mips, a target address is stored in a lui/ori instruction pair, each |
| 3025 // of which load 16 bits of the 32-bit address to a register. | 3125 // of which load 16 bits of the 32-bit address to a register. |
| 3026 // Patching the address must replace both instr, and flush the i-cache. | 3126 // Patching the address must replace both instr, and flush the i-cache. |
| 3127 // On r6, target address is stored in a lui/jic pair, and both instr have to be | |
| 3128 // patched. | |
| 3027 // | 3129 // |
| 3028 // There is an optimization below, which emits a nop when the address | 3130 // There is an optimization below, which emits a nop when the address |
| 3029 // fits in just 16 bits. This is unlikely to help, and should be benchmarked, | 3131 // fits in just 16 bits. This is unlikely to help, and should be benchmarked, |
| 3030 // and possibly removed. | 3132 // and possibly removed. |
| 3031 void Assembler::set_target_address_at(Isolate* isolate, Address pc, | 3133 void Assembler::set_target_address_at(Isolate* isolate, Address pc, |
| 3032 Address target, | 3134 Address target, |
| 3033 ICacheFlushMode icache_flush_mode) { | 3135 ICacheFlushMode icache_flush_mode) { |
| 3034 Instr instr2 = instr_at(pc + kInstrSize); | 3136 Instr instr2 = instr_at(pc + kInstrSize); |
| 3035 uint32_t rt_code = GetRtField(instr2); | 3137 uint32_t rt_code = GetRtField(instr2); |
| 3036 uint32_t* p = reinterpret_cast<uint32_t*>(pc); | 3138 uint32_t* p = reinterpret_cast<uint32_t*>(pc); |
| 3037 uint32_t itarget = reinterpret_cast<uint32_t>(target); | 3139 uint32_t itarget = reinterpret_cast<uint32_t>(target); |
| 3038 | 3140 |
| 3039 #ifdef DEBUG | 3141 #ifdef DEBUG |
| 3040 // Check we have the result from a li macro-instruction, using instr pair. | 3142 // Check we have the result from a li macro-instruction, using instr pair. |
| 3041 Instr instr1 = instr_at(pc); | 3143 Instr instr1 = instr_at(pc); |
| 3042 CHECK((GetOpcodeField(instr1) == LUI && GetOpcodeField(instr2) == ORI)); | 3144 CHECK(IsLui(instr1) && (IsOri(instr2) || IsJicOrJialc(instr2))); |
| 3043 #endif | 3145 #endif |
| 3044 | 3146 |
| 3045 // Must use 2 instructions to insure patchable code => just use lui and ori. | 3147 if (IsJicOrJialc(instr2)) { |
| 3046 // lui rt, upper-16. | 3148 // Must use 2 instructions to insure patchable code => use lui and jic |
| 3047 // ori rt rt, lower-16. | 3149 uint32_t lui_offset, jic_offset; |
| 3048 *p = LUI | rt_code | ((itarget & kHiMask) >> kLuiShift); | 3150 Assembler::UnpackTargetAddressUnsigned(itarget, lui_offset, jic_offset); |
| 3049 *(p + 1) = ORI | rt_code | (rt_code << 5) | (itarget & kImm16Mask); | |
| 3050 | 3151 |
| 3152 *p &= ~kImm16Mask; | |
| 3153 *(p + 1) &= ~kImm16Mask; | |
| 3154 | |
| 3155 *p |= lui_offset; | |
| 3156 *(p + 1) |= jic_offset; | |
| 3157 | |
| 3158 } else { | |
| 3159 // Must use 2 instructions to insure patchable code => just use lui and ori. | |
| 3160 // lui rt, upper-16. | |
| 3161 // ori rt rt, lower-16. | |
| 3162 *p = LUI | rt_code | ((itarget & kHiMask) >> kLuiShift); | |
| 3163 *(p + 1) = ORI | rt_code | (rt_code << 5) | (itarget & kImm16Mask); | |
| 3164 } | |
| 3051 | 3165 |
| 3052 if (icache_flush_mode != SKIP_ICACHE_FLUSH) { | 3166 if (icache_flush_mode != SKIP_ICACHE_FLUSH) { |
| 3053 Assembler::FlushICache(isolate, pc, 2 * sizeof(int32_t)); | 3167 Assembler::FlushICache(isolate, pc, 2 * sizeof(int32_t)); |
| 3054 } | 3168 } |
| 3055 } | 3169 } |
| 3056 | 3170 |
| 3057 } // namespace internal | 3171 } // namespace internal |
| 3058 } // namespace v8 | 3172 } // namespace v8 |
| 3059 | 3173 |
| 3060 #endif // V8_TARGET_ARCH_MIPS | 3174 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |