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