| 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 |