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

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, 11 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 523 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698