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 619 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
630 if ((instr & ~kImm16Mask) == 0) { | 630 if ((instr & ~kImm16Mask) == 0) { |
631 // Emitted label constant, not part of a branch. | 631 // Emitted label constant, not part of a branch. |
632 if (instr == 0) { | 632 if (instr == 0) { |
633 return kEndOfChain; | 633 return kEndOfChain; |
634 } else { | 634 } else { |
635 int32_t imm18 =((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14; | 635 int32_t imm18 =((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14; |
636 return (imm18 + pos); | 636 return (imm18 + pos); |
637 } | 637 } |
638 } | 638 } |
639 // Check we have a branch or jump instruction. | 639 // Check we have a branch or jump instruction. |
640 DCHECK(IsBranch(instr) || IsJ(instr) || IsLui(instr)); | 640 DCHECK(IsBranch(instr) || IsLui(instr)); |
641 // Do NOT change this to <<2. We rely on arithmetic shifts here, assuming | 641 // Do NOT change this to <<2. We rely on arithmetic shifts here, assuming |
642 // the compiler uses arithmetic shifts for signed integers. | 642 // the compiler uses arithmetic shifts for signed integers. |
643 if (IsBranch(instr)) { | 643 if (IsBranch(instr)) { |
644 int32_t imm18 = ((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14; | 644 int32_t imm18 = ((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14; |
645 if (imm18 == kEndOfChain) { | 645 if (imm18 == kEndOfChain) { |
646 // EndOfChain sentinel is returned directly, not relative to pc or pos. | 646 // EndOfChain sentinel is returned directly, not relative to pc or pos. |
647 return kEndOfChain; | 647 return kEndOfChain; |
648 } else { | 648 } else { |
649 return pos + kBranchPCOffset + imm18; | 649 return pos + kBranchPCOffset + imm18; |
650 } | 650 } |
(...skipping 15 matching lines...) Expand all Loading... |
666 // EndOfChain sentinel is returned directly, not relative to pc or pos. | 666 // EndOfChain sentinel is returned directly, not relative to pc or pos. |
667 return kEndOfChain; | 667 return kEndOfChain; |
668 } else { | 668 } else { |
669 uint64_t instr_address = reinterpret_cast<int64_t>(buffer_ + pos); | 669 uint64_t instr_address = reinterpret_cast<int64_t>(buffer_ + pos); |
670 DCHECK(instr_address - imm < INT_MAX); | 670 DCHECK(instr_address - imm < INT_MAX); |
671 int delta = static_cast<int>(instr_address - imm); | 671 int delta = static_cast<int>(instr_address - imm); |
672 DCHECK(pos > delta); | 672 DCHECK(pos > delta); |
673 return pos - delta; | 673 return pos - delta; |
674 } | 674 } |
675 } else { | 675 } else { |
676 int32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2; | 676 UNREACHABLE(); |
677 if (imm28 == kEndOfJumpChain) { | 677 return 0; |
678 // EndOfChain sentinel is returned directly, not relative to pc or pos. | |
679 return kEndOfChain; | |
680 } else { | |
681 uint64_t instr_address = reinterpret_cast<int64_t>(buffer_ + pos); | |
682 instr_address &= kImm28Mask; | |
683 int delta = static_cast<int>(instr_address - imm28); | |
684 DCHECK(pos > delta); | |
685 return pos - delta; | |
686 } | |
687 } | 678 } |
688 } | 679 } |
689 | 680 |
690 | 681 |
691 void Assembler::target_at_put(int pos, int target_pos, bool is_internal) { | 682 void Assembler::target_at_put(int pos, int target_pos, bool is_internal) { |
692 if (is_internal) { | 683 if (is_internal) { |
693 uint64_t imm = reinterpret_cast<uint64_t>(buffer_) + target_pos; | 684 uint64_t imm = reinterpret_cast<uint64_t>(buffer_) + target_pos; |
694 *reinterpret_cast<uint64_t*>(buffer_ + pos) = imm; | 685 *reinterpret_cast<uint64_t*>(buffer_ + pos) = imm; |
695 return; | 686 return; |
696 } | 687 } |
697 Instr instr = instr_at(pos); | 688 Instr instr = instr_at(pos); |
698 if ((instr & ~kImm16Mask) == 0) { | 689 if ((instr & ~kImm16Mask) == 0) { |
699 DCHECK(target_pos == kEndOfChain || target_pos >= 0); | 690 DCHECK(target_pos == kEndOfChain || target_pos >= 0); |
700 // Emitted label constant, not part of a branch. | 691 // Emitted label constant, not part of a branch. |
701 // Make label relative to Code* of generated Code object. | 692 // Make label relative to Code* of generated Code object. |
702 instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag)); | 693 instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag)); |
703 return; | 694 return; |
704 } | 695 } |
705 | 696 |
706 DCHECK(IsBranch(instr) || IsJ(instr) || IsLui(instr)); | 697 DCHECK(IsBranch(instr) || IsLui(instr)); |
707 if (IsBranch(instr)) { | 698 if (IsBranch(instr)) { |
708 int32_t imm18 = target_pos - (pos + kBranchPCOffset); | 699 int32_t imm18 = target_pos - (pos + kBranchPCOffset); |
709 DCHECK((imm18 & 3) == 0); | 700 DCHECK((imm18 & 3) == 0); |
710 | 701 |
711 instr &= ~kImm16Mask; | 702 instr &= ~kImm16Mask; |
712 int32_t imm16 = imm18 >> 2; | 703 int32_t imm16 = imm18 >> 2; |
713 DCHECK(is_int16(imm16)); | 704 DCHECK(is_int16(imm16)); |
714 | 705 |
715 instr_at_put(pos, instr | (imm16 & kImm16Mask)); | 706 instr_at_put(pos, instr | (imm16 & kImm16Mask)); |
716 } else if (IsLui(instr)) { | 707 } else if (IsLui(instr)) { |
(...skipping 10 matching lines...) Expand all Loading... |
727 instr_ori &= ~kImm16Mask; | 718 instr_ori &= ~kImm16Mask; |
728 instr_ori2 &= ~kImm16Mask; | 719 instr_ori2 &= ~kImm16Mask; |
729 | 720 |
730 instr_at_put(pos + 0 * Assembler::kInstrSize, | 721 instr_at_put(pos + 0 * Assembler::kInstrSize, |
731 instr_lui | ((imm >> 32) & kImm16Mask)); | 722 instr_lui | ((imm >> 32) & kImm16Mask)); |
732 instr_at_put(pos + 1 * Assembler::kInstrSize, | 723 instr_at_put(pos + 1 * Assembler::kInstrSize, |
733 instr_ori | ((imm >> 16) & kImm16Mask)); | 724 instr_ori | ((imm >> 16) & kImm16Mask)); |
734 instr_at_put(pos + 3 * Assembler::kInstrSize, | 725 instr_at_put(pos + 3 * Assembler::kInstrSize, |
735 instr_ori2 | (imm & kImm16Mask)); | 726 instr_ori2 | (imm & kImm16Mask)); |
736 } else { | 727 } else { |
737 uint64_t imm28 = reinterpret_cast<uint64_t>(buffer_) + target_pos; | 728 UNREACHABLE(); |
738 imm28 &= kImm28Mask; | |
739 DCHECK((imm28 & 3) == 0); | |
740 | |
741 instr &= ~kImm26Mask; | |
742 uint32_t imm26 = imm28 >> 2; | |
743 DCHECK(is_uint26(imm26)); | |
744 | |
745 instr_at_put(pos, instr | (imm26 & kImm26Mask)); | |
746 } | 729 } |
747 } | 730 } |
748 | 731 |
749 | 732 |
750 void Assembler::print(Label* L) { | 733 void Assembler::print(Label* L) { |
751 if (L->is_unused()) { | 734 if (L->is_unused()) { |
752 PrintF("unused label\n"); | 735 PrintF("unused label\n"); |
753 } else if (L->is_bound()) { | 736 } else if (L->is_bound()) { |
754 PrintF("bound label to %d\n", L->pos()); | 737 PrintF("bound label to %d\n", L->pos()); |
755 } else if (L->is_linked()) { | 738 } else if (L->is_linked()) { |
(...skipping 1833 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2589 if (RelocInfo::IsInternalReference(rmode)) { | 2572 if (RelocInfo::IsInternalReference(rmode)) { |
2590 int64_t* p = reinterpret_cast<int64_t*>(pc); | 2573 int64_t* p = reinterpret_cast<int64_t*>(pc); |
2591 if (*p == kEndOfJumpChain) { | 2574 if (*p == kEndOfJumpChain) { |
2592 return 0; // Number of instructions patched. | 2575 return 0; // Number of instructions patched. |
2593 } | 2576 } |
2594 *p += pc_delta; | 2577 *p += pc_delta; |
2595 return 2; // Number of instructions patched. | 2578 return 2; // Number of instructions patched. |
2596 } | 2579 } |
2597 Instr instr = instr_at(pc); | 2580 Instr instr = instr_at(pc); |
2598 DCHECK(RelocInfo::IsInternalReferenceEncoded(rmode)); | 2581 DCHECK(RelocInfo::IsInternalReferenceEncoded(rmode)); |
2599 DCHECK(IsJ(instr) || IsLui(instr)); | |
2600 if (IsLui(instr)) { | 2582 if (IsLui(instr)) { |
2601 Instr instr_lui = instr_at(pc + 0 * Assembler::kInstrSize); | 2583 Instr instr_lui = instr_at(pc + 0 * Assembler::kInstrSize); |
2602 Instr instr_ori = instr_at(pc + 1 * Assembler::kInstrSize); | 2584 Instr instr_ori = instr_at(pc + 1 * Assembler::kInstrSize); |
2603 Instr instr_ori2 = instr_at(pc + 3 * Assembler::kInstrSize); | 2585 Instr instr_ori2 = instr_at(pc + 3 * Assembler::kInstrSize); |
2604 DCHECK(IsOri(instr_ori)); | 2586 DCHECK(IsOri(instr_ori)); |
2605 DCHECK(IsOri(instr_ori2)); | 2587 DCHECK(IsOri(instr_ori2)); |
2606 // TODO(plind): symbolic names for the shifts. | 2588 // TODO(plind): symbolic names for the shifts. |
2607 int64_t imm = (instr_lui & static_cast<int64_t>(kImm16Mask)) << 48; | 2589 int64_t imm = (instr_lui & static_cast<int64_t>(kImm16Mask)) << 48; |
2608 imm |= (instr_ori & static_cast<int64_t>(kImm16Mask)) << 32; | 2590 imm |= (instr_ori & static_cast<int64_t>(kImm16Mask)) << 32; |
2609 imm |= (instr_ori2 & static_cast<int64_t>(kImm16Mask)) << 16; | 2591 imm |= (instr_ori2 & static_cast<int64_t>(kImm16Mask)) << 16; |
(...skipping 11 matching lines...) Expand all Loading... |
2621 instr_ori2 &= ~kImm16Mask; | 2603 instr_ori2 &= ~kImm16Mask; |
2622 | 2604 |
2623 instr_at_put(pc + 0 * Assembler::kInstrSize, | 2605 instr_at_put(pc + 0 * Assembler::kInstrSize, |
2624 instr_lui | ((imm >> 32) & kImm16Mask)); | 2606 instr_lui | ((imm >> 32) & kImm16Mask)); |
2625 instr_at_put(pc + 1 * Assembler::kInstrSize, | 2607 instr_at_put(pc + 1 * Assembler::kInstrSize, |
2626 instr_ori | (imm >> 16 & kImm16Mask)); | 2608 instr_ori | (imm >> 16 & kImm16Mask)); |
2627 instr_at_put(pc + 3 * Assembler::kInstrSize, | 2609 instr_at_put(pc + 3 * Assembler::kInstrSize, |
2628 instr_ori2 | (imm & kImm16Mask)); | 2610 instr_ori2 | (imm & kImm16Mask)); |
2629 return 4; // Number of instructions patched. | 2611 return 4; // Number of instructions patched. |
2630 } else { | 2612 } else { |
2631 uint32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2; | 2613 UNREACHABLE(); |
2632 if (static_cast<int32_t>(imm28) == kEndOfJumpChain) { | 2614 return 0; // Number of instructions patched. |
2633 return 0; // Number of instructions patched. | |
2634 } | |
2635 | |
2636 imm28 += pc_delta; | |
2637 imm28 &= kImm28Mask; | |
2638 DCHECK((imm28 & 3) == 0); | |
2639 | |
2640 instr &= ~kImm26Mask; | |
2641 uint32_t imm26 = imm28 >> 2; | |
2642 DCHECK(is_uint26(imm26)); | |
2643 | |
2644 instr_at_put(pc, instr | (imm26 & kImm26Mask)); | |
2645 return 1; // Number of instructions patched. | |
2646 } | 2615 } |
2647 } | 2616 } |
2648 | 2617 |
2649 | 2618 |
2650 void Assembler::GrowBuffer() { | 2619 void Assembler::GrowBuffer() { |
2651 if (!own_buffer_) FATAL("external code buffer is too small"); | 2620 if (!own_buffer_) FATAL("external code buffer is too small"); |
2652 | 2621 |
2653 // Compute new buffer size. | 2622 // Compute new buffer size. |
2654 CodeDesc desc; // The new buffer. | 2623 CodeDesc desc; // The new buffer. |
2655 if (buffer_size_ < 1 * MB) { | 2624 if (buffer_size_ < 1 * MB) { |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2909 | ((itarget >> 16) & kImm16Mask); | 2878 | ((itarget >> 16) & kImm16Mask); |
2910 *(p + 3) = ORI | (rt_code << kRsShift) | (rt_code << kRtShift) | 2879 *(p + 3) = ORI | (rt_code << kRsShift) | (rt_code << kRtShift) |
2911 | (itarget & kImm16Mask); | 2880 | (itarget & kImm16Mask); |
2912 | 2881 |
2913 if (icache_flush_mode != SKIP_ICACHE_FLUSH) { | 2882 if (icache_flush_mode != SKIP_ICACHE_FLUSH) { |
2914 CpuFeatures::FlushICache(pc, 4 * Assembler::kInstrSize); | 2883 CpuFeatures::FlushICache(pc, 4 * Assembler::kInstrSize); |
2915 } | 2884 } |
2916 } | 2885 } |
2917 | 2886 |
2918 | 2887 |
2919 void Assembler::JumpLabelToJumpRegister(Address pc) { | |
2920 // Address pc points to lui/ori instructions. | |
2921 // Jump to label may follow at pc + 2 * kInstrSize. | |
2922 uint32_t* p = reinterpret_cast<uint32_t*>(pc); | |
2923 #ifdef DEBUG | |
2924 Instr instr1 = instr_at(pc); | |
2925 #endif | |
2926 Instr instr2 = instr_at(pc + 1 * kInstrSize); | |
2927 Instr instr3 = instr_at(pc + 6 * kInstrSize); | |
2928 bool patched = false; | |
2929 | |
2930 if (IsJal(instr3)) { | |
2931 DCHECK(GetOpcodeField(instr1) == LUI); | |
2932 DCHECK(GetOpcodeField(instr2) == ORI); | |
2933 | |
2934 uint32_t rs_field = GetRt(instr2) << kRsShift; | |
2935 uint32_t rd_field = ra.code() << kRdShift; // Return-address (ra) reg. | |
2936 *(p+6) = SPECIAL | rs_field | rd_field | JALR; | |
2937 patched = true; | |
2938 } else if (IsJ(instr3)) { | |
2939 DCHECK(GetOpcodeField(instr1) == LUI); | |
2940 DCHECK(GetOpcodeField(instr2) == ORI); | |
2941 | |
2942 uint32_t rs_field = GetRt(instr2) << kRsShift; | |
2943 *(p+6) = SPECIAL | rs_field | JR; | |
2944 patched = true; | |
2945 } | |
2946 | |
2947 if (patched) { | |
2948 CpuFeatures::FlushICache(pc+6, sizeof(int32_t)); | |
2949 } | |
2950 } | |
2951 | |
2952 | |
2953 Handle<ConstantPoolArray> Assembler::NewConstantPool(Isolate* isolate) { | 2888 Handle<ConstantPoolArray> Assembler::NewConstantPool(Isolate* isolate) { |
2954 // No out-of-line constant pool support. | 2889 // No out-of-line constant pool support. |
2955 DCHECK(!FLAG_enable_ool_constant_pool); | 2890 DCHECK(!FLAG_enable_ool_constant_pool); |
2956 return isolate->factory()->empty_constant_pool_array(); | 2891 return isolate->factory()->empty_constant_pool_array(); |
2957 } | 2892 } |
2958 | 2893 |
2959 | 2894 |
2960 void Assembler::PopulateConstantPool(ConstantPoolArray* constant_pool) { | 2895 void Assembler::PopulateConstantPool(ConstantPoolArray* constant_pool) { |
2961 // No out-of-line constant pool support. | 2896 // No out-of-line constant pool support. |
2962 DCHECK(!FLAG_enable_ool_constant_pool); | 2897 DCHECK(!FLAG_enable_ool_constant_pool); |
2963 return; | 2898 return; |
2964 } | 2899 } |
2965 | 2900 |
2966 | 2901 |
2967 } } // namespace v8::internal | 2902 } } // namespace v8::internal |
2968 | 2903 |
2969 #endif // V8_TARGET_ARCH_MIPS64 | 2904 #endif // V8_TARGET_ARCH_MIPS64 |
OLD | NEW |