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 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 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
190 ra | 190 ra |
191 }; | 191 }; |
192 return kRegisters[num]; | 192 return kRegisters[num]; |
193 } | 193 } |
194 | 194 |
195 | 195 |
196 // ----------------------------------------------------------------------------- | 196 // ----------------------------------------------------------------------------- |
197 // Implementation of RelocInfo. | 197 // Implementation of RelocInfo. |
198 | 198 |
199 const int RelocInfo::kApplyMask = RelocInfo::kCodeTargetMask | | 199 const int RelocInfo::kApplyMask = RelocInfo::kCodeTargetMask | |
200 1 << RelocInfo::INTERNAL_REFERENCE | | 200 1 << RelocInfo::INTERNAL_REFERENCE; |
201 1 << RelocInfo::INTERNAL_REFERENCE_ENCODED; | |
202 | 201 |
203 | 202 |
204 bool RelocInfo::IsCodedSpecially() { | 203 bool RelocInfo::IsCodedSpecially() { |
205 // The deserializer needs to know whether a pointer is specially coded. Being | 204 // The deserializer needs to know whether a pointer is specially coded. Being |
206 // specially coded on MIPS means that it is a lui/ori instruction, and that is | 205 // specially coded on MIPS means that it is a lui/ori instruction, and that is |
207 // always the case inside code objects. | 206 // always the case inside code objects. |
208 return true; | 207 return true; |
209 } | 208 } |
210 | 209 |
211 | 210 |
(...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
656 DCHECK(IsAddImmediate(instr)); | 655 DCHECK(IsAddImmediate(instr)); |
657 return ((instr & ~kImm16Mask) | (offset & kImm16Mask)); | 656 return ((instr & ~kImm16Mask) | (offset & kImm16Mask)); |
658 } | 657 } |
659 | 658 |
660 | 659 |
661 bool Assembler::IsAndImmediate(Instr instr) { | 660 bool Assembler::IsAndImmediate(Instr instr) { |
662 return GetOpcodeField(instr) == ANDI; | 661 return GetOpcodeField(instr) == ANDI; |
663 } | 662 } |
664 | 663 |
665 | 664 |
666 int Assembler::target_at(int32_t pos, bool is_internal) { | 665 int Assembler::target_at(int32_t pos) { |
667 Instr instr = instr_at(pos); | 666 Instr instr = instr_at(pos); |
668 if (is_internal) { | |
669 if (instr == 0) { | |
670 return kEndOfChain; | |
671 } else { | |
672 int32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos); | |
673 int32_t delta = instr_address - instr; | |
674 DCHECK(pos > delta); | |
675 return pos - delta; | |
676 } | |
677 } | |
678 if ((instr & ~kImm16Mask) == 0) { | 667 if ((instr & ~kImm16Mask) == 0) { |
679 // Emitted label constant, not part of a branch. | 668 // Emitted label constant, not part of a branch. |
680 if (instr == 0) { | 669 if (instr == 0) { |
681 return kEndOfChain; | 670 return kEndOfChain; |
682 } else { | 671 } else { |
683 int32_t imm18 =((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14; | 672 int32_t imm18 =((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14; |
684 return (imm18 + pos); | 673 return (imm18 + pos); |
685 } | 674 } |
686 } | 675 } |
687 // Do NOT change this to <<2. We rely on arithmetic shifts here, assuming | 676 // Do NOT change this to <<2. We rely on arithmetic shifts here, assuming |
(...skipping 28 matching lines...) Expand all Loading... |
716 if (imm28 == kEndOfJumpChain) { | 705 if (imm28 == kEndOfJumpChain) { |
717 // EndOfChain sentinel is returned directly, not relative to pc or pos. | 706 // EndOfChain sentinel is returned directly, not relative to pc or pos. |
718 return kEndOfChain; | 707 return kEndOfChain; |
719 } else { | 708 } else { |
720 uint32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos); | 709 uint32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos); |
721 instr_address &= kImm28Mask; | 710 instr_address &= kImm28Mask; |
722 int32_t delta = instr_address - imm28; | 711 int32_t delta = instr_address - imm28; |
723 DCHECK(pos > delta); | 712 DCHECK(pos > delta); |
724 return pos - delta; | 713 return pos - delta; |
725 } | 714 } |
726 } else { | 715 } else { // IsLabel(instr) |
727 UNREACHABLE(); | 716 int32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2; |
728 return 0; | 717 if (imm28 == kEndOfJumpChain) { |
| 718 // EndOfChain sentinel is returned directly, not relative to pc or pos. |
| 719 return kEndOfChain; |
| 720 } else { |
| 721 return pos + imm28; |
| 722 } |
729 } | 723 } |
730 } | 724 } |
731 | 725 |
732 | 726 |
733 void Assembler::target_at_put(int32_t pos, int32_t target_pos, | 727 void Assembler::target_at_put(int32_t pos, int32_t target_pos) { |
734 bool is_internal) { | |
735 Instr instr = instr_at(pos); | 728 Instr instr = instr_at(pos); |
736 | |
737 if (is_internal) { | |
738 uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos; | |
739 instr_at_put(pos, imm); | |
740 return; | |
741 } | |
742 if ((instr & ~kImm16Mask) == 0) { | 729 if ((instr & ~kImm16Mask) == 0) { |
743 DCHECK(target_pos == kEndOfChain || target_pos >= 0); | 730 DCHECK(target_pos == kEndOfChain || target_pos >= 0); |
744 // Emitted label constant, not part of a branch. | 731 // Emitted label constant, not part of a branch. |
745 // Make label relative to Code* of generated Code object. | 732 // Make label relative to Code* of generated Code object. |
746 instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag)); | 733 instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag)); |
747 return; | 734 return; |
748 } | 735 } |
749 | 736 |
750 if (IsBranch(instr)) { | 737 if (IsBranch(instr)) { |
751 int32_t imm18 = target_pos - (pos + kBranchPCOffset); | 738 int32_t imm18 = target_pos - (pos + kBranchPCOffset); |
(...skipping 22 matching lines...) Expand all Loading... |
774 uint32_t imm28 = reinterpret_cast<uint32_t>(buffer_) + target_pos; | 761 uint32_t imm28 = reinterpret_cast<uint32_t>(buffer_) + target_pos; |
775 imm28 &= kImm28Mask; | 762 imm28 &= kImm28Mask; |
776 DCHECK((imm28 & 3) == 0); | 763 DCHECK((imm28 & 3) == 0); |
777 | 764 |
778 instr &= ~kImm26Mask; | 765 instr &= ~kImm26Mask; |
779 uint32_t imm26 = imm28 >> 2; | 766 uint32_t imm26 = imm28 >> 2; |
780 DCHECK(is_uint26(imm26)); | 767 DCHECK(is_uint26(imm26)); |
781 | 768 |
782 instr_at_put(pos, instr | (imm26 & kImm26Mask)); | 769 instr_at_put(pos, instr | (imm26 & kImm26Mask)); |
783 } else { | 770 } else { |
784 UNREACHABLE(); | 771 uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos; |
| 772 instr_at_put(pos, imm); |
785 } | 773 } |
786 } | 774 } |
787 | 775 |
788 | 776 |
789 void Assembler::print(Label* L) { | 777 void Assembler::print(Label* L) { |
790 if (L->is_unused()) { | 778 if (L->is_unused()) { |
791 PrintF("unused label\n"); | 779 PrintF("unused label\n"); |
792 } else if (L->is_bound()) { | 780 } else if (L->is_bound()) { |
793 PrintF("bound label to %d\n", L->pos()); | 781 PrintF("bound label to %d\n", L->pos()); |
794 } else if (L->is_linked()) { | 782 } else if (L->is_linked()) { |
795 Label l = *L; | 783 Label l = *L; |
796 PrintF("unbound label"); | 784 PrintF("unbound label"); |
797 while (l.is_linked()) { | 785 while (l.is_linked()) { |
798 PrintF("@ %d ", l.pos()); | 786 PrintF("@ %d ", l.pos()); |
799 Instr instr = instr_at(l.pos()); | 787 Instr instr = instr_at(l.pos()); |
800 if ((instr & ~kImm16Mask) == 0) { | 788 if ((instr & ~kImm16Mask) == 0) { |
801 PrintF("value\n"); | 789 PrintF("value\n"); |
802 } else { | 790 } else { |
803 PrintF("%d\n", instr); | 791 PrintF("%d\n", instr); |
804 } | 792 } |
805 next(&l, internal_reference_positions_.find(l.pos()) != | 793 next(&l); |
806 internal_reference_positions_.end()); | |
807 } | 794 } |
808 } else { | 795 } else { |
809 PrintF("label in inconsistent state (pos = %d)\n", L->pos_); | 796 PrintF("label in inconsistent state (pos = %d)\n", L->pos_); |
810 } | 797 } |
811 } | 798 } |
812 | 799 |
813 | 800 |
814 void Assembler::bind_to(Label* L, int pos) { | 801 void Assembler::bind_to(Label* L, int pos) { |
815 DCHECK(0 <= pos && pos <= pc_offset()); // Must have valid binding position. | 802 DCHECK(0 <= pos && pos <= pc_offset()); // Must have valid binding position. |
816 int32_t trampoline_pos = kInvalidSlotPos; | 803 int32_t trampoline_pos = kInvalidSlotPos; |
817 bool is_internal = false; | |
818 if (L->is_linked() && !trampoline_emitted_) { | 804 if (L->is_linked() && !trampoline_emitted_) { |
819 unbound_labels_count_--; | 805 unbound_labels_count_--; |
820 next_buffer_check_ += kTrampolineSlotsSize; | 806 next_buffer_check_ += kTrampolineSlotsSize; |
821 } | 807 } |
822 | 808 |
823 while (L->is_linked()) { | 809 while (L->is_linked()) { |
824 int32_t fixup_pos = L->pos(); | 810 int32_t fixup_pos = L->pos(); |
825 int32_t dist = pos - fixup_pos; | 811 int32_t dist = pos - fixup_pos; |
826 is_internal = internal_reference_positions_.find(fixup_pos) != | 812 next(L); // Call next before overwriting link with target at fixup_pos. |
827 internal_reference_positions_.end(); | |
828 next(L, is_internal); // Call next before overwriting link with target at | |
829 // fixup_pos. | |
830 Instr instr = instr_at(fixup_pos); | 813 Instr instr = instr_at(fixup_pos); |
831 if (is_internal) { | 814 if (IsBranch(instr)) { |
832 target_at_put(fixup_pos, pos, is_internal); | |
833 } else if (!is_internal && IsBranch(instr)) { | |
834 if (dist > kMaxBranchOffset) { | 815 if (dist > kMaxBranchOffset) { |
835 if (trampoline_pos == kInvalidSlotPos) { | 816 if (trampoline_pos == kInvalidSlotPos) { |
836 trampoline_pos = get_trampoline_entry(fixup_pos); | 817 trampoline_pos = get_trampoline_entry(fixup_pos); |
837 CHECK(trampoline_pos != kInvalidSlotPos); | 818 CHECK(trampoline_pos != kInvalidSlotPos); |
838 } | 819 } |
839 DCHECK((trampoline_pos - fixup_pos) <= kMaxBranchOffset); | 820 DCHECK((trampoline_pos - fixup_pos) <= kMaxBranchOffset); |
840 target_at_put(fixup_pos, trampoline_pos, false); | 821 target_at_put(fixup_pos, trampoline_pos); |
841 fixup_pos = trampoline_pos; | 822 fixup_pos = trampoline_pos; |
842 dist = pos - fixup_pos; | 823 dist = pos - fixup_pos; |
843 } | 824 } |
844 target_at_put(fixup_pos, pos, false); | 825 target_at_put(fixup_pos, pos); |
845 } else { | 826 } else { |
846 target_at_put(fixup_pos, pos, false); | 827 target_at_put(fixup_pos, pos); |
847 } | 828 } |
848 } | 829 } |
849 L->bind_to(pos); | 830 L->bind_to(pos); |
850 | 831 |
851 // Keep track of the last bound label so we don't eliminate any instructions | 832 // Keep track of the last bound label so we don't eliminate any instructions |
852 // before a bound label. | 833 // before a bound label. |
853 if (pos > last_bound_pos_) | 834 if (pos > last_bound_pos_) |
854 last_bound_pos_ = pos; | 835 last_bound_pos_ = pos; |
855 } | 836 } |
856 | 837 |
857 | 838 |
858 void Assembler::bind(Label* L) { | 839 void Assembler::bind(Label* L) { |
859 DCHECK(!L->is_bound()); // Label can only be bound once. | 840 DCHECK(!L->is_bound()); // Label can only be bound once. |
860 bind_to(L, pc_offset()); | 841 bind_to(L, pc_offset()); |
861 } | 842 } |
862 | 843 |
863 | 844 |
864 void Assembler::next(Label* L, bool is_internal) { | 845 void Assembler::next(Label* L) { |
865 DCHECK(L->is_linked()); | 846 DCHECK(L->is_linked()); |
866 int link = target_at(L->pos(), is_internal); | 847 int link = target_at(L->pos()); |
867 if (link == kEndOfChain) { | 848 if (link == kEndOfChain) { |
868 L->Unuse(); | 849 L->Unuse(); |
869 } else { | 850 } else { |
870 DCHECK(link >= 0); | 851 DCHECK(link >= 0); |
871 L->link_to(link); | 852 L->link_to(link); |
872 } | 853 } |
873 } | 854 } |
874 | 855 |
875 | 856 |
876 bool Assembler::is_near(Label* L) { | 857 bool Assembler::is_near(Label* L) { |
(...skipping 1467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2344 | 2325 |
2345 | 2326 |
2346 void Assembler::bc1t(int16_t offset, uint16_t cc) { | 2327 void Assembler::bc1t(int16_t offset, uint16_t cc) { |
2347 DCHECK(is_uint3(cc)); | 2328 DCHECK(is_uint3(cc)); |
2348 Instr instr = COP1 | BC1 | cc << 18 | 1 << 16 | (offset & kImm16Mask); | 2329 Instr instr = COP1 | BC1 | cc << 18 | 1 << 16 | (offset & kImm16Mask); |
2349 emit(instr); | 2330 emit(instr); |
2350 } | 2331 } |
2351 | 2332 |
2352 | 2333 |
2353 // Debugging. | 2334 // Debugging. |
2354 int Assembler::RelocateInternalReference(RelocInfo::Mode rmode, byte* pc, | 2335 int Assembler::RelocateInternalReference(byte* pc, intptr_t pc_delta) { |
2355 intptr_t pc_delta) { | |
2356 Instr instr = instr_at(pc); | 2336 Instr instr = instr_at(pc); |
| 2337 if (IsLui(instr)) { |
| 2338 Instr instr_lui = instr_at(pc + 0 * Assembler::kInstrSize); |
| 2339 Instr instr_ori = instr_at(pc + 1 * Assembler::kInstrSize); |
| 2340 DCHECK(IsOri(instr_ori)); |
| 2341 int32_t imm = (instr_lui & static_cast<int32_t>(kImm16Mask)) << kLuiShift; |
| 2342 imm |= (instr_ori & static_cast<int32_t>(kImm16Mask)); |
| 2343 if (imm == kEndOfJumpChain) { |
| 2344 return 0; // Number of instructions patched. |
| 2345 } |
| 2346 imm += pc_delta; |
| 2347 DCHECK((imm & 3) == 0); |
2357 | 2348 |
2358 if (RelocInfo::IsInternalReference(rmode)) { | 2349 instr_lui &= ~kImm16Mask; |
| 2350 instr_ori &= ~kImm16Mask; |
| 2351 |
| 2352 instr_at_put(pc + 0 * Assembler::kInstrSize, |
| 2353 instr_lui | ((imm >> kLuiShift) & kImm16Mask)); |
| 2354 instr_at_put(pc + 1 * Assembler::kInstrSize, |
| 2355 instr_ori | (imm & kImm16Mask)); |
| 2356 return 2; // Number of instructions patched. |
| 2357 } else if (IsJ(instr)) { |
| 2358 uint32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2; |
| 2359 if (static_cast<int32_t>(imm28) == kEndOfJumpChain) { |
| 2360 return 0; // Number of instructions patched. |
| 2361 } |
| 2362 imm28 += pc_delta; |
| 2363 imm28 &= kImm28Mask; |
| 2364 DCHECK((imm28 & 3) == 0); |
| 2365 |
| 2366 instr &= ~kImm26Mask; |
| 2367 uint32_t imm26 = imm28 >> 2; |
| 2368 DCHECK(is_uint26(imm26)); |
| 2369 |
| 2370 instr_at_put(pc, instr | (imm26 & kImm26Mask)); |
| 2371 return 1; // Number of instructions patched. |
| 2372 } else { // IsLabel(instr) |
2359 int32_t* p = reinterpret_cast<int32_t*>(pc); | 2373 int32_t* p = reinterpret_cast<int32_t*>(pc); |
2360 if (*p == 0) { | 2374 uint32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2; |
| 2375 if (static_cast<int32_t>(imm28) == kEndOfJumpChain) { |
2361 return 0; // Number of instructions patched. | 2376 return 0; // Number of instructions patched. |
2362 } | 2377 } |
2363 *p += pc_delta; | 2378 *p += pc_delta; |
2364 return 1; // Number of instructions patched. | 2379 return 1; // Number of instructions patched. |
2365 } else { | |
2366 DCHECK(RelocInfo::IsInternalReferenceEncoded(rmode)); | |
2367 if (IsLui(instr)) { | |
2368 Instr instr_lui = instr_at(pc + 0 * Assembler::kInstrSize); | |
2369 Instr instr_ori = instr_at(pc + 1 * Assembler::kInstrSize); | |
2370 DCHECK(IsOri(instr_ori)); | |
2371 int32_t imm = (instr_lui & static_cast<int32_t>(kImm16Mask)) << kLuiShift; | |
2372 imm |= (instr_ori & static_cast<int32_t>(kImm16Mask)); | |
2373 if (imm == kEndOfJumpChain) { | |
2374 return 0; // Number of instructions patched. | |
2375 } | |
2376 imm += pc_delta; | |
2377 DCHECK((imm & 3) == 0); | |
2378 | |
2379 instr_lui &= ~kImm16Mask; | |
2380 instr_ori &= ~kImm16Mask; | |
2381 | |
2382 instr_at_put(pc + 0 * Assembler::kInstrSize, | |
2383 instr_lui | ((imm >> kLuiShift) & kImm16Mask)); | |
2384 instr_at_put(pc + 1 * Assembler::kInstrSize, | |
2385 instr_ori | (imm & kImm16Mask)); | |
2386 return 2; // Number of instructions patched. | |
2387 } else if (IsJ(instr)) { | |
2388 uint32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2; | |
2389 if (static_cast<int32_t>(imm28) == kEndOfJumpChain) { | |
2390 return 0; // Number of instructions patched. | |
2391 } | |
2392 imm28 += pc_delta; | |
2393 imm28 &= kImm28Mask; | |
2394 DCHECK((imm28 & 3) == 0); | |
2395 | |
2396 instr &= ~kImm26Mask; | |
2397 uint32_t imm26 = imm28 >> 2; | |
2398 DCHECK(is_uint26(imm26)); | |
2399 | |
2400 instr_at_put(pc, instr | (imm26 & kImm26Mask)); | |
2401 return 1; // Number of instructions patched. | |
2402 } else { | |
2403 UNREACHABLE(); | |
2404 return 0; | |
2405 } | |
2406 } | 2380 } |
2407 } | 2381 } |
2408 | 2382 |
2409 | 2383 |
2410 void Assembler::GrowBuffer() { | 2384 void Assembler::GrowBuffer() { |
2411 if (!own_buffer_) FATAL("external code buffer is too small"); | 2385 if (!own_buffer_) FATAL("external code buffer is too small"); |
2412 | 2386 |
2413 // Compute new buffer size. | 2387 // Compute new buffer size. |
2414 CodeDesc desc; // The new buffer. | 2388 CodeDesc desc; // The new buffer. |
2415 if (buffer_size_ < 1 * MB) { | 2389 if (buffer_size_ < 1 * MB) { |
(...skipping 20 matching lines...) Expand all Loading... |
2436 DeleteArray(buffer_); | 2410 DeleteArray(buffer_); |
2437 buffer_ = desc.buffer; | 2411 buffer_ = desc.buffer; |
2438 buffer_size_ = desc.buffer_size; | 2412 buffer_size_ = desc.buffer_size; |
2439 pc_ += pc_delta; | 2413 pc_ += pc_delta; |
2440 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta, | 2414 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta, |
2441 reloc_info_writer.last_pc() + pc_delta); | 2415 reloc_info_writer.last_pc() + pc_delta); |
2442 | 2416 |
2443 // Relocate runtime entries. | 2417 // Relocate runtime entries. |
2444 for (RelocIterator it(desc); !it.done(); it.next()) { | 2418 for (RelocIterator it(desc); !it.done(); it.next()) { |
2445 RelocInfo::Mode rmode = it.rinfo()->rmode(); | 2419 RelocInfo::Mode rmode = it.rinfo()->rmode(); |
2446 if (rmode == RelocInfo::INTERNAL_REFERENCE_ENCODED || | 2420 if (rmode == RelocInfo::INTERNAL_REFERENCE) { |
2447 rmode == RelocInfo::INTERNAL_REFERENCE) { | |
2448 byte* p = reinterpret_cast<byte*>(it.rinfo()->pc()); | 2421 byte* p = reinterpret_cast<byte*>(it.rinfo()->pc()); |
2449 RelocateInternalReference(rmode, p, pc_delta); | 2422 RelocateInternalReference(p, pc_delta); |
2450 } | 2423 } |
2451 } | 2424 } |
| 2425 |
2452 DCHECK(!overflow()); | 2426 DCHECK(!overflow()); |
2453 } | 2427 } |
2454 | 2428 |
2455 | 2429 |
2456 void Assembler::db(uint8_t data) { | 2430 void Assembler::db(uint8_t data) { |
2457 CheckBuffer(); | 2431 CheckBuffer(); |
2458 *reinterpret_cast<uint8_t*>(pc_) = data; | 2432 *reinterpret_cast<uint8_t*>(pc_) = data; |
2459 pc_ += sizeof(uint8_t); | 2433 pc_ += sizeof(uint8_t); |
2460 } | 2434 } |
2461 | 2435 |
2462 | 2436 |
2463 void Assembler::dd(uint32_t data) { | 2437 void Assembler::dd(uint32_t data) { |
2464 CheckBuffer(); | 2438 CheckBuffer(); |
2465 *reinterpret_cast<uint32_t*>(pc_) = data; | 2439 *reinterpret_cast<uint32_t*>(pc_) = data; |
2466 pc_ += sizeof(uint32_t); | 2440 pc_ += sizeof(uint32_t); |
2467 } | 2441 } |
2468 | 2442 |
2469 | 2443 |
2470 void Assembler::dd(Label* label) { | 2444 void Assembler::dd(Label* label) { |
2471 CheckBuffer(); | 2445 CheckBuffer(); |
2472 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE); | 2446 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE); |
2473 if (label->is_bound()) { | 2447 if (label->is_bound()) { |
2474 uint32_t data = reinterpret_cast<uint32_t>(buffer_ + label->pos()); | 2448 uint32_t data = reinterpret_cast<uint32_t>(buffer_ + label->pos()); |
2475 *reinterpret_cast<uint32_t*>(pc_) = data; | 2449 *reinterpret_cast<uint32_t*>(pc_) = data; |
2476 pc_ += sizeof(uint32_t); | 2450 pc_ += sizeof(uint32_t); |
2477 } else { | 2451 } else { |
2478 uint32_t target_pos = jump_address(label); | 2452 int target_pos; |
2479 emit(target_pos); | 2453 if (label->is_linked()) { |
2480 internal_reference_positions_.insert(label->pos()); | 2454 // Point to previous instruction that uses the link. |
| 2455 target_pos = label->pos(); |
| 2456 } else { |
| 2457 // First entry of the link chain points to itself. |
| 2458 target_pos = pc_offset(); |
| 2459 } |
| 2460 label->link_to(pc_offset()); |
| 2461 // Encode internal reference to unbound label. We set the least significant |
| 2462 // bit to distinguish unbound internal references in GrowBuffer() below. |
| 2463 int diff = target_pos - pc_offset(); |
| 2464 DCHECK_EQ(0, diff & 3); |
| 2465 int imm26 = diff >> 2; |
| 2466 DCHECK(is_int26(imm26)); |
| 2467 // Emit special LABEL instruction. |
| 2468 emit(LABEL | (imm26 & kImm26Mask)); |
2481 } | 2469 } |
2482 } | 2470 } |
2483 | 2471 |
2484 | 2472 |
2485 void Assembler::emit_code_stub_address(Code* stub) { | 2473 void Assembler::emit_code_stub_address(Code* stub) { |
2486 CheckBuffer(); | 2474 CheckBuffer(); |
2487 *reinterpret_cast<uint32_t*>(pc_) = | 2475 *reinterpret_cast<uint32_t*>(pc_) = |
2488 reinterpret_cast<uint32_t>(stub->instruction_start()); | 2476 reinterpret_cast<uint32_t>(stub->instruction_start()); |
2489 pc_ += sizeof(uint32_t); | 2477 pc_ += sizeof(uint32_t); |
2490 } | 2478 } |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2555 nop(); | 2543 nop(); |
2556 | 2544 |
2557 int pool_start = pc_offset(); | 2545 int pool_start = pc_offset(); |
2558 for (int i = 0; i < unbound_labels_count_; i++) { | 2546 for (int i = 0; i < unbound_labels_count_; i++) { |
2559 uint32_t imm32; | 2547 uint32_t imm32; |
2560 imm32 = jump_address(&after_pool); | 2548 imm32 = jump_address(&after_pool); |
2561 { BlockGrowBufferScope block_buf_growth(this); | 2549 { BlockGrowBufferScope block_buf_growth(this); |
2562 // Buffer growth (and relocation) must be blocked for internal | 2550 // Buffer growth (and relocation) must be blocked for internal |
2563 // references until associated instructions are emitted and available | 2551 // references until associated instructions are emitted and available |
2564 // to be patched. | 2552 // to be patched. |
2565 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE_ENCODED); | 2553 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE); |
2566 lui(at, (imm32 & kHiMask) >> kLuiShift); | 2554 lui(at, (imm32 & kHiMask) >> kLuiShift); |
2567 ori(at, at, (imm32 & kImm16Mask)); | 2555 ori(at, at, (imm32 & kImm16Mask)); |
2568 } | 2556 } |
2569 jr(at); | 2557 jr(at); |
2570 nop(); | 2558 nop(); |
2571 } | 2559 } |
2572 bind(&after_pool); | 2560 bind(&after_pool); |
2573 trampoline_ = Trampoline(pool_start, unbound_labels_count_); | 2561 trampoline_ = Trampoline(pool_start, unbound_labels_count_); |
2574 | 2562 |
2575 trampoline_emitted_ = true; | 2563 trampoline_emitted_ = true; |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2773 void Assembler::PopulateConstantPool(ConstantPoolArray* constant_pool) { | 2761 void Assembler::PopulateConstantPool(ConstantPoolArray* constant_pool) { |
2774 // No out-of-line constant pool support. | 2762 // No out-of-line constant pool support. |
2775 DCHECK(!FLAG_enable_ool_constant_pool); | 2763 DCHECK(!FLAG_enable_ool_constant_pool); |
2776 return; | 2764 return; |
2777 } | 2765 } |
2778 | 2766 |
2779 | 2767 |
2780 } } // namespace v8::internal | 2768 } } // namespace v8::internal |
2781 | 2769 |
2782 #endif // V8_TARGET_ARCH_MIPS | 2770 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |