Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(230)

Side by Side Diff: src/mips/assembler-mips.cc

Issue 1573983002: MIPS: Replace JR/JALR with JIC/JIALC for r6 (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698