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