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 | 5 // modification, are permitted provided that the following conditions |
6 // are met: | 6 // are 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 668 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
679 | 679 |
680 // Labels refer to positions in the (to be) generated code. | 680 // Labels refer to positions in the (to be) generated code. |
681 // There are bound, linked, and unused labels. | 681 // There are bound, linked, and unused labels. |
682 // | 682 // |
683 // Bound labels refer to known positions in the already | 683 // Bound labels refer to known positions in the already |
684 // generated code. pos() is the position the label refers to. | 684 // generated code. pos() is the position the label refers to. |
685 // | 685 // |
686 // Linked labels refer to unknown positions in the code | 686 // Linked labels refer to unknown positions in the code |
687 // to be generated; pos() is the position of the last | 687 // to be generated; pos() is the position of the last |
688 // instruction using the label. | 688 // instruction using the label. |
689 | 689 // |
690 | 690 // The linked labels form a link chain by making the branch offset |
691 // The link chain is terminated by a negative code position (must be aligned) | 691 // in the instruction steam to point to the previous branch |
692 const int kEndOfChain = -4; | 692 // instruction using the same label. |
| 693 // |
| 694 // The link chain is terminated by a branch offset pointing to the |
| 695 // same position. |
693 | 696 |
694 | 697 |
695 int Assembler::target_at(int pos) { | 698 int Assembler::target_at(int pos) { |
696 Instr instr = instr_at(pos); | 699 Instr instr = instr_at(pos); |
697 if ((instr & ~kImm24Mask) == 0) { | 700 if ((instr & ~kImm24Mask) == 0) { |
698 // Emitted label constant, not part of a branch. | 701 // Emitted label constant, not part of a branch. |
699 return instr - (Code::kHeaderSize - kHeapObjectTag); | 702 return instr - (Code::kHeaderSize - kHeapObjectTag); |
700 } | 703 } |
701 ASSERT((instr & 7*B25) == 5*B25); // b, bl, or blx imm24 | 704 ASSERT((instr & 7*B25) == 5*B25); // b, bl, or blx imm24 |
702 int imm26 = ((instr & kImm24Mask) << 8) >> 6; | 705 int imm26 = ((instr & kImm24Mask) << 8) >> 6; |
703 if ((Instruction::ConditionField(instr) == kSpecialCondition) && | 706 if ((Instruction::ConditionField(instr) == kSpecialCondition) && |
704 ((instr & B24) != 0)) { | 707 ((instr & B24) != 0)) { |
705 // blx uses bit 24 to encode bit 2 of imm26 | 708 // blx uses bit 24 to encode bit 2 of imm26 |
706 imm26 += 2; | 709 imm26 += 2; |
707 } | 710 } |
708 return pos + kPcLoadDelta + imm26; | 711 return pos + kPcLoadDelta + imm26; |
709 } | 712 } |
710 | 713 |
711 | 714 |
712 void Assembler::target_at_put(int pos, int target_pos) { | 715 void Assembler::target_at_put(int pos, int target_pos) { |
713 Instr instr = instr_at(pos); | 716 Instr instr = instr_at(pos); |
714 if ((instr & ~kImm24Mask) == 0) { | 717 if ((instr & ~kImm24Mask) == 0) { |
715 ASSERT(target_pos == kEndOfChain || target_pos >= 0); | 718 ASSERT(target_pos == pos || target_pos >= 0); |
716 // Emitted label constant, not part of a branch. | 719 // Emitted label constant, not part of a branch. |
717 // Make label relative to Code* of generated Code object. | 720 // Make label relative to Code* of generated Code object. |
718 instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag)); | 721 instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag)); |
719 return; | 722 return; |
720 } | 723 } |
721 int imm26 = target_pos - (pos + kPcLoadDelta); | 724 int imm26 = target_pos - (pos + kPcLoadDelta); |
722 ASSERT((instr & 7*B25) == 5*B25); // b, bl, or blx imm24 | 725 ASSERT((instr & 7*B25) == 5*B25); // b, bl, or blx imm24 |
723 if (Instruction::ConditionField(instr) == kSpecialCondition) { | 726 if (Instruction::ConditionField(instr) == kSpecialCondition) { |
724 // blx uses bit 24 to encode bit 2 of imm26 | 727 // blx uses bit 24 to encode bit 2 of imm26 |
725 ASSERT((imm26 & 1) == 0); | 728 ASSERT((imm26 & 1) == 0); |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
801 } | 804 } |
802 L->bind_to(pos); | 805 L->bind_to(pos); |
803 | 806 |
804 // Keep track of the last bound label so we don't eliminate any instructions | 807 // Keep track of the last bound label so we don't eliminate any instructions |
805 // before a bound label. | 808 // before a bound label. |
806 if (pos > last_bound_pos_) | 809 if (pos > last_bound_pos_) |
807 last_bound_pos_ = pos; | 810 last_bound_pos_ = pos; |
808 } | 811 } |
809 | 812 |
810 | 813 |
811 void Assembler::link_to(Label* L, Label* appendix) { | |
812 if (appendix->is_linked()) { | |
813 if (L->is_linked()) { | |
814 // Append appendix to L's list. | |
815 int fixup_pos; | |
816 int link = L->pos(); | |
817 do { | |
818 fixup_pos = link; | |
819 link = target_at(fixup_pos); | |
820 } while (link > 0); | |
821 ASSERT(link == kEndOfChain); | |
822 target_at_put(fixup_pos, appendix->pos()); | |
823 } else { | |
824 // L is empty, simply use appendix. | |
825 *L = *appendix; | |
826 } | |
827 } | |
828 appendix->Unuse(); // appendix should not be used anymore | |
829 } | |
830 | |
831 | |
832 void Assembler::bind(Label* L) { | 814 void Assembler::bind(Label* L) { |
833 ASSERT(!L->is_bound()); // label can only be bound once | 815 ASSERT(!L->is_bound()); // label can only be bound once |
834 bind_to(L, pc_offset()); | 816 bind_to(L, pc_offset()); |
835 } | 817 } |
836 | 818 |
837 | 819 |
838 void Assembler::next(Label* L) { | 820 void Assembler::next(Label* L) { |
839 ASSERT(L->is_linked()); | 821 ASSERT(L->is_linked()); |
840 int link = target_at(L->pos()); | 822 int link = target_at(L->pos()); |
841 if (link == kEndOfChain) { | 823 if (link == L->pos()) { |
| 824 // Branch target points to the same instuction. This is the end of the link |
| 825 // chain. |
842 L->Unuse(); | 826 L->Unuse(); |
843 } else { | 827 } else { |
844 ASSERT(link >= 0); | 828 ASSERT(link >= 0); |
845 L->link_to(link); | 829 L->link_to(link); |
846 } | 830 } |
847 } | 831 } |
848 | 832 |
849 | 833 |
850 // Low-level code emission routines depending on the addressing mode. | 834 // Low-level code emission routines depending on the addressing mode. |
851 // If this returns true then you have to use the rotate_imm and immed_8 | 835 // If this returns true then you have to use the rotate_imm and immed_8 |
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1144 emit(instr | am | x.rn_.code()*B16 | crd.code()*B12 | offset_8); | 1128 emit(instr | am | x.rn_.code()*B16 | crd.code()*B12 | offset_8); |
1145 } | 1129 } |
1146 | 1130 |
1147 | 1131 |
1148 int Assembler::branch_offset(Label* L, bool jump_elimination_allowed) { | 1132 int Assembler::branch_offset(Label* L, bool jump_elimination_allowed) { |
1149 int target_pos; | 1133 int target_pos; |
1150 if (L->is_bound()) { | 1134 if (L->is_bound()) { |
1151 target_pos = L->pos(); | 1135 target_pos = L->pos(); |
1152 } else { | 1136 } else { |
1153 if (L->is_linked()) { | 1137 if (L->is_linked()) { |
1154 target_pos = L->pos(); // L's link | 1138 // Point to previous instruction that uses the link. |
| 1139 target_pos = L->pos(); |
1155 } else { | 1140 } else { |
1156 target_pos = kEndOfChain; | 1141 // First entry of the link chain points to itself. |
| 1142 target_pos = pc_offset(); |
1157 } | 1143 } |
1158 L->link_to(pc_offset()); | 1144 L->link_to(pc_offset()); |
1159 } | 1145 } |
1160 | 1146 |
1161 // Block the emission of the constant pool, since the branch instruction must | 1147 // Block the emission of the constant pool, since the branch instruction must |
1162 // be emitted at the pc offset recorded by the label. | 1148 // be emitted at the pc offset recorded by the label. |
1163 BlockConstPoolFor(1); | 1149 BlockConstPoolFor(1); |
1164 return target_pos - (pc_offset() + kPcLoadDelta); | 1150 return target_pos - (pc_offset() + kPcLoadDelta); |
1165 } | 1151 } |
1166 | 1152 |
1167 | 1153 |
1168 void Assembler::label_at_put(Label* L, int at_offset) { | 1154 void Assembler::label_at_put(Label* L, int at_offset) { |
1169 int target_pos; | 1155 int target_pos; |
1170 if (L->is_bound()) { | 1156 ASSERT(!L->is_bound()); |
| 1157 if (L->is_linked()) { |
| 1158 // Point to previous instruction that uses the link. |
1171 target_pos = L->pos(); | 1159 target_pos = L->pos(); |
1172 } else { | 1160 } else { |
1173 if (L->is_linked()) { | 1161 // First entry of the link chain points to itself. |
1174 target_pos = L->pos(); // L's link | 1162 target_pos = at_offset; |
1175 } else { | |
1176 target_pos = kEndOfChain; | |
1177 } | |
1178 L->link_to(at_offset); | |
1179 instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag)); | |
1180 } | 1163 } |
| 1164 L->link_to(at_offset); |
| 1165 instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag)); |
1181 } | 1166 } |
1182 | 1167 |
1183 | 1168 |
1184 // Branch instructions. | 1169 // Branch instructions. |
1185 void Assembler::b(int branch_offset, Condition cond) { | 1170 void Assembler::b(int branch_offset, Condition cond) { |
1186 ASSERT((branch_offset & 3) == 0); | 1171 ASSERT((branch_offset & 3) == 0); |
1187 int imm24 = branch_offset >> 2; | 1172 int imm24 = branch_offset >> 2; |
1188 ASSERT(is_int24(imm24)); | 1173 ASSERT(is_int24(imm24)); |
1189 emit(cond | B27 | B25 | (imm24 & kImm24Mask)); | 1174 emit(cond | B27 | B25 | (imm24 & kImm24Mask)); |
1190 | 1175 |
(...skipping 1911 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3102 | 3087 |
3103 // Since a constant pool was just emitted, move the check offset forward by | 3088 // Since a constant pool was just emitted, move the check offset forward by |
3104 // the standard interval. | 3089 // the standard interval. |
3105 next_buffer_check_ = pc_offset() + kCheckPoolInterval; | 3090 next_buffer_check_ = pc_offset() + kCheckPoolInterval; |
3106 } | 3091 } |
3107 | 3092 |
3108 | 3093 |
3109 } } // namespace v8::internal | 3094 } } // namespace v8::internal |
3110 | 3095 |
3111 #endif // V8_TARGET_ARCH_ARM | 3096 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |