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