| 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 746 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 757 | 757 |
| 758 // Labels refer to positions in the (to be) generated code. | 758 // Labels refer to positions in the (to be) generated code. |
| 759 // There are bound, linked, and unused labels. | 759 // There are bound, linked, and unused labels. |
| 760 // | 760 // |
| 761 // Bound labels refer to known positions in the already | 761 // Bound labels refer to known positions in the already |
| 762 // generated code. pos() is the position the label refers to. | 762 // generated code. pos() is the position the label refers to. |
| 763 // | 763 // |
| 764 // Linked labels refer to unknown positions in the code | 764 // Linked labels refer to unknown positions in the code |
| 765 // to be generated; pos() is the position of the last | 765 // to be generated; pos() is the position of the last |
| 766 // instruction using the label. | 766 // instruction using the label. |
| 767 | 767 // |
| 768 | 768 // The linked labels form a link chain by making the branch offset |
| 769 // The link chain is terminated by a negative code position (must be aligned) | 769 // in the instruction steam to point to the previous branch |
| 770 const int kEndOfChain = -4; | 770 // instruction using the same label. |
| 771 // |
| 772 // The link chain is terminated by a branch offset pointing to the |
| 773 // same position. |
| 771 | 774 |
| 772 | 775 |
| 773 int Assembler::target_at(int pos) { | 776 int Assembler::target_at(int pos) { |
| 774 Instr instr = instr_at(pos); | 777 Instr instr = instr_at(pos); |
| 775 if ((instr & ~kImm24Mask) == 0) { | 778 if ((instr & ~kImm24Mask) == 0) { |
| 776 // Emitted label constant, not part of a branch. | 779 // Emitted label constant, not part of a branch. |
| 777 return instr - (Code::kHeaderSize - kHeapObjectTag); | 780 return instr - (Code::kHeaderSize - kHeapObjectTag); |
| 778 } | 781 } |
| 779 ASSERT((instr & 7*B25) == 5*B25); // b, bl, or blx imm24 | 782 ASSERT((instr & 7*B25) == 5*B25); // b, bl, or blx imm24 |
| 780 int imm26 = ((instr & kImm24Mask) << 8) >> 6; | 783 int imm26 = ((instr & kImm24Mask) << 8) >> 6; |
| 781 if ((Instruction::ConditionField(instr) == kSpecialCondition) && | 784 if ((Instruction::ConditionField(instr) == kSpecialCondition) && |
| 782 ((instr & B24) != 0)) { | 785 ((instr & B24) != 0)) { |
| 783 // blx uses bit 24 to encode bit 2 of imm26 | 786 // blx uses bit 24 to encode bit 2 of imm26 |
| 784 imm26 += 2; | 787 imm26 += 2; |
| 785 } | 788 } |
| 786 return pos + kPcLoadDelta + imm26; | 789 return pos + kPcLoadDelta + imm26; |
| 787 } | 790 } |
| 788 | 791 |
| 789 | 792 |
| 790 void Assembler::target_at_put(int pos, int target_pos) { | 793 void Assembler::target_at_put(int pos, int target_pos) { |
| 791 Instr instr = instr_at(pos); | 794 Instr instr = instr_at(pos); |
| 792 if ((instr & ~kImm24Mask) == 0) { | 795 if ((instr & ~kImm24Mask) == 0) { |
| 793 ASSERT(target_pos == kEndOfChain || target_pos >= 0); | 796 ASSERT(target_pos == pos || target_pos >= 0); |
| 794 // Emitted label constant, not part of a branch. | 797 // Emitted label constant, not part of a branch. |
| 795 // Make label relative to Code* of generated Code object. | 798 // Make label relative to Code* of generated Code object. |
| 796 instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag)); | 799 instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag)); |
| 797 return; | 800 return; |
| 798 } | 801 } |
| 799 int imm26 = target_pos - (pos + kPcLoadDelta); | 802 int imm26 = target_pos - (pos + kPcLoadDelta); |
| 800 ASSERT((instr & 7*B25) == 5*B25); // b, bl, or blx imm24 | 803 ASSERT((instr & 7*B25) == 5*B25); // b, bl, or blx imm24 |
| 801 if (Instruction::ConditionField(instr) == kSpecialCondition) { | 804 if (Instruction::ConditionField(instr) == kSpecialCondition) { |
| 802 // blx uses bit 24 to encode bit 2 of imm26 | 805 // blx uses bit 24 to encode bit 2 of imm26 |
| 803 ASSERT((imm26 & 1) == 0); | 806 ASSERT((imm26 & 1) == 0); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 879 } | 882 } |
| 880 L->bind_to(pos); | 883 L->bind_to(pos); |
| 881 | 884 |
| 882 // Keep track of the last bound label so we don't eliminate any instructions | 885 // Keep track of the last bound label so we don't eliminate any instructions |
| 883 // before a bound label. | 886 // before a bound label. |
| 884 if (pos > last_bound_pos_) | 887 if (pos > last_bound_pos_) |
| 885 last_bound_pos_ = pos; | 888 last_bound_pos_ = pos; |
| 886 } | 889 } |
| 887 | 890 |
| 888 | 891 |
| 889 void Assembler::link_to(Label* L, Label* appendix) { | |
| 890 if (appendix->is_linked()) { | |
| 891 if (L->is_linked()) { | |
| 892 // Append appendix to L's list. | |
| 893 int fixup_pos; | |
| 894 int link = L->pos(); | |
| 895 do { | |
| 896 fixup_pos = link; | |
| 897 link = target_at(fixup_pos); | |
| 898 } while (link > 0); | |
| 899 ASSERT(link == kEndOfChain); | |
| 900 target_at_put(fixup_pos, appendix->pos()); | |
| 901 } else { | |
| 902 // L is empty, simply use appendix. | |
| 903 *L = *appendix; | |
| 904 } | |
| 905 } | |
| 906 appendix->Unuse(); // appendix should not be used anymore | |
| 907 } | |
| 908 | |
| 909 | |
| 910 void Assembler::bind(Label* L) { | 892 void Assembler::bind(Label* L) { |
| 911 ASSERT(!L->is_bound()); // label can only be bound once | 893 ASSERT(!L->is_bound()); // label can only be bound once |
| 912 bind_to(L, pc_offset()); | 894 bind_to(L, pc_offset()); |
| 913 } | 895 } |
| 914 | 896 |
| 915 | 897 |
| 916 void Assembler::next(Label* L) { | 898 void Assembler::next(Label* L) { |
| 917 ASSERT(L->is_linked()); | 899 ASSERT(L->is_linked()); |
| 918 int link = target_at(L->pos()); | 900 int link = target_at(L->pos()); |
| 919 if (link == kEndOfChain) { | 901 if (link == L->pos()) { |
| 902 // Branch target points to the same instuction. This is the end of the link |
| 903 // chain. |
| 920 L->Unuse(); | 904 L->Unuse(); |
| 921 } else { | 905 } else { |
| 922 ASSERT(link >= 0); | 906 ASSERT(link >= 0); |
| 923 L->link_to(link); | 907 L->link_to(link); |
| 924 } | 908 } |
| 925 } | 909 } |
| 926 | 910 |
| 927 | 911 |
| 928 // Low-level code emission routines depending on the addressing mode. | 912 // Low-level code emission routines depending on the addressing mode. |
| 929 // If this returns true then you have to use the rotate_imm and immed_8 | 913 // 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... |
| 1222 emit(instr | am | x.rn_.code()*B16 | crd.code()*B12 | offset_8); | 1206 emit(instr | am | x.rn_.code()*B16 | crd.code()*B12 | offset_8); |
| 1223 } | 1207 } |
| 1224 | 1208 |
| 1225 | 1209 |
| 1226 int Assembler::branch_offset(Label* L, bool jump_elimination_allowed) { | 1210 int Assembler::branch_offset(Label* L, bool jump_elimination_allowed) { |
| 1227 int target_pos; | 1211 int target_pos; |
| 1228 if (L->is_bound()) { | 1212 if (L->is_bound()) { |
| 1229 target_pos = L->pos(); | 1213 target_pos = L->pos(); |
| 1230 } else { | 1214 } else { |
| 1231 if (L->is_linked()) { | 1215 if (L->is_linked()) { |
| 1232 target_pos = L->pos(); // L's link | 1216 // Point to previous instruction that uses the link. |
| 1217 target_pos = L->pos(); |
| 1233 } else { | 1218 } else { |
| 1234 target_pos = kEndOfChain; | 1219 // First entry of the link chain points to itself. |
| 1220 target_pos = pc_offset(); |
| 1235 } | 1221 } |
| 1236 L->link_to(pc_offset()); | 1222 L->link_to(pc_offset()); |
| 1237 } | 1223 } |
| 1238 | 1224 |
| 1239 // Block the emission of the constant pool, since the branch instruction must | 1225 // Block the emission of the constant pool, since the branch instruction must |
| 1240 // be emitted at the pc offset recorded by the label. | 1226 // be emitted at the pc offset recorded by the label. |
| 1241 BlockConstPoolFor(1); | 1227 BlockConstPoolFor(1); |
| 1242 return target_pos - (pc_offset() + kPcLoadDelta); | 1228 return target_pos - (pc_offset() + kPcLoadDelta); |
| 1243 } | 1229 } |
| 1244 | 1230 |
| 1245 | 1231 |
| 1246 void Assembler::label_at_put(Label* L, int at_offset) { | 1232 void Assembler::label_at_put(Label* L, int at_offset) { |
| 1247 int target_pos; | 1233 int target_pos; |
| 1248 if (L->is_bound()) { | 1234 ASSERT(!L->is_bound()); |
| 1235 if (L->is_linked()) { |
| 1236 // Point to previous instruction that uses the link. |
| 1249 target_pos = L->pos(); | 1237 target_pos = L->pos(); |
| 1250 } else { | 1238 } else { |
| 1251 if (L->is_linked()) { | 1239 // First entry of the link chain points to itself. |
| 1252 target_pos = L->pos(); // L's link | 1240 target_pos = at_offset; |
| 1253 } else { | |
| 1254 target_pos = kEndOfChain; | |
| 1255 } | |
| 1256 L->link_to(at_offset); | |
| 1257 instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag)); | |
| 1258 } | 1241 } |
| 1242 L->link_to(at_offset); |
| 1243 instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag)); |
| 1259 } | 1244 } |
| 1260 | 1245 |
| 1261 | 1246 |
| 1262 // Branch instructions. | 1247 // Branch instructions. |
| 1263 void Assembler::b(int branch_offset, Condition cond) { | 1248 void Assembler::b(int branch_offset, Condition cond) { |
| 1264 ASSERT((branch_offset & 3) == 0); | 1249 ASSERT((branch_offset & 3) == 0); |
| 1265 int imm24 = branch_offset >> 2; | 1250 int imm24 = branch_offset >> 2; |
| 1266 ASSERT(is_int24(imm24)); | 1251 ASSERT(is_int24(imm24)); |
| 1267 emit(cond | B27 | B25 | (imm24 & kImm24Mask)); | 1252 emit(cond | B27 | B25 | (imm24 & kImm24Mask)); |
| 1268 | 1253 |
| (...skipping 2097 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3366 | 3351 |
| 3367 // Since a constant pool was just emitted, move the check offset forward by | 3352 // Since a constant pool was just emitted, move the check offset forward by |
| 3368 // the standard interval. | 3353 // the standard interval. |
| 3369 next_buffer_check_ = pc_offset() + kCheckPoolInterval; | 3354 next_buffer_check_ = pc_offset() + kCheckPoolInterval; |
| 3370 } | 3355 } |
| 3371 | 3356 |
| 3372 | 3357 |
| 3373 } } // namespace v8::internal | 3358 } } // namespace v8::internal |
| 3374 | 3359 |
| 3375 #endif // V8_TARGET_ARCH_ARM | 3360 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |