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