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 |