| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // | 2 // |
| 3 // Redistribution and use in source and binary forms, with or without | 3 // Redistribution and use in source and binary forms, with or without |
| 4 // modification, are permitted provided that the following conditions are | 4 // modification, are permitted provided that the following conditions are |
| 5 // met: | 5 // met: |
| 6 // | 6 // |
| 7 // * Redistributions of source code must retain the above copyright | 7 // * Redistributions of source code must retain the above copyright |
| 8 // notice, this list of conditions and the following disclaimer. | 8 // notice, this list of conditions and the following disclaimer. |
| 9 // * Redistributions in binary form must reproduce the above | 9 // * Redistributions in binary form must reproduce the above |
| 10 // copyright notice, this list of conditions and the following | 10 // copyright notice, this list of conditions and the following |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 // Add the link register (x30) to the safepoint list. | 164 // Add the link register (x30) to the safepoint list. |
| 165 list.Combine(30); | 165 list.Combine(30); |
| 166 | 166 |
| 167 return list; | 167 return list; |
| 168 } | 168 } |
| 169 | 169 |
| 170 | 170 |
| 171 // ----------------------------------------------------------------------------- | 171 // ----------------------------------------------------------------------------- |
| 172 // Implementation of RelocInfo | 172 // Implementation of RelocInfo |
| 173 | 173 |
| 174 const int RelocInfo::kApplyMask = 0; | 174 const int RelocInfo::kApplyMask = 1 << RelocInfo::INTERNAL_REFERENCE; |
| 175 | 175 |
| 176 | 176 |
| 177 bool RelocInfo::IsCodedSpecially() { | 177 bool RelocInfo::IsCodedSpecially() { |
| 178 // The deserializer needs to know whether a pointer is specially coded. Being | 178 // The deserializer needs to know whether a pointer is specially coded. Being |
| 179 // specially coded on ARM64 means that it is a movz/movk sequence. We don't | 179 // specially coded on ARM64 means that it is a movz/movk sequence. We don't |
| 180 // generate those for relocatable pointers. | 180 // generate those for relocatable pointers. |
| 181 return false; | 181 return false; |
| 182 } | 182 } |
| 183 | 183 |
| 184 | 184 |
| (...skipping 540 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 725 | 725 |
| 726 CheckLabelLinkChain(label); | 726 CheckLabelLinkChain(label); |
| 727 | 727 |
| 728 DCHECK(linkoffset >= 0); | 728 DCHECK(linkoffset >= 0); |
| 729 DCHECK(linkoffset < pc_offset()); | 729 DCHECK(linkoffset < pc_offset()); |
| 730 DCHECK((linkoffset > prevlinkoffset) || | 730 DCHECK((linkoffset > prevlinkoffset) || |
| 731 (linkoffset - prevlinkoffset == kStartOfLabelLinkChain)); | 731 (linkoffset - prevlinkoffset == kStartOfLabelLinkChain)); |
| 732 DCHECK(prevlinkoffset >= 0); | 732 DCHECK(prevlinkoffset >= 0); |
| 733 | 733 |
| 734 // Update the link to point to the label. | 734 // Update the link to point to the label. |
| 735 link->SetImmPCOffsetTarget(reinterpret_cast<Instruction*>(pc_)); | 735 if (link->IsUnresolvedInternalReference()) { |
| 736 // Internal references do not get patched to an instruction but directly |
| 737 // to an address. |
| 738 internal_reference_positions_.push_back(linkoffset); |
| 739 PatchingAssembler patcher(link, 2); |
| 740 patcher.dc64(reinterpret_cast<uintptr_t>(pc_)); |
| 741 } else { |
| 742 link->SetImmPCOffsetTarget(reinterpret_cast<Instruction*>(pc_)); |
| 743 } |
| 736 | 744 |
| 737 // Link the label to the previous link in the chain. | 745 // Link the label to the previous link in the chain. |
| 738 if (linkoffset - prevlinkoffset == kStartOfLabelLinkChain) { | 746 if (linkoffset - prevlinkoffset == kStartOfLabelLinkChain) { |
| 739 // We hit kStartOfLabelLinkChain, so the chain is fully processed. | 747 // We hit kStartOfLabelLinkChain, so the chain is fully processed. |
| 740 label->Unuse(); | 748 label->Unuse(); |
| 741 } else { | 749 } else { |
| 742 // Update the label for the next iteration. | 750 // Update the label for the next iteration. |
| 743 label->link_to(prevlinkoffset); | 751 label->link_to(prevlinkoffset); |
| 744 } | 752 } |
| 745 } | 753 } |
| (...skipping 1307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2053 unsigned fbits) { | 2061 unsigned fbits) { |
| 2054 if (fbits == 0) { | 2062 if (fbits == 0) { |
| 2055 Emit(SF(rn) | FPType(fd) | UCVTF | Rn(rn) | Rd(fd)); | 2063 Emit(SF(rn) | FPType(fd) | UCVTF | Rn(rn) | Rd(fd)); |
| 2056 } else { | 2064 } else { |
| 2057 Emit(SF(rn) | FPType(fd) | UCVTF_fixed | FPScale(64 - fbits) | Rn(rn) | | 2065 Emit(SF(rn) | FPType(fd) | UCVTF_fixed | FPScale(64 - fbits) | Rn(rn) | |
| 2058 Rd(fd)); | 2066 Rd(fd)); |
| 2059 } | 2067 } |
| 2060 } | 2068 } |
| 2061 | 2069 |
| 2062 | 2070 |
| 2071 void Assembler::dcptr(Label* label) { |
| 2072 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE); |
| 2073 if (label->is_bound()) { |
| 2074 // The label is bound, so it does not need to be updated and the internal |
| 2075 // reference should be emitted. |
| 2076 // |
| 2077 // In this case, label->pos() returns the offset of the label from the |
| 2078 // start of the buffer. |
| 2079 internal_reference_positions_.push_back(pc_offset()); |
| 2080 dc64(reinterpret_cast<uintptr_t>(buffer_ + label->pos())); |
| 2081 } else { |
| 2082 int32_t offset; |
| 2083 if (label->is_linked()) { |
| 2084 // The label is linked, so the internal reference should be added |
| 2085 // onto the end of the label's link chain. |
| 2086 // |
| 2087 // In this case, label->pos() returns the offset of the last linked |
| 2088 // instruction from the start of the buffer. |
| 2089 offset = label->pos() - pc_offset(); |
| 2090 DCHECK(offset != kStartOfLabelLinkChain); |
| 2091 } else { |
| 2092 // The label is unused, so it now becomes linked and the internal |
| 2093 // reference is at the start of the new link chain. |
| 2094 offset = kStartOfLabelLinkChain; |
| 2095 } |
| 2096 // The instruction at pc is now the last link in the label's chain. |
| 2097 label->link_to(pc_offset()); |
| 2098 |
| 2099 // Traditionally the offset to the previous instruction in the chain is |
| 2100 // encoded in the instruction payload (e.g. branch range) but internal |
| 2101 // references are not instructions so while unbound they are encoded as |
| 2102 // two consecutive brk instructions. The two 16-bit immediates are used |
| 2103 // to encode the offset. |
| 2104 offset >>= kInstructionSizeLog2; |
| 2105 DCHECK(is_int32(offset)); |
| 2106 uint32_t high16 = unsigned_bitextract_32(31, 16, offset); |
| 2107 uint32_t low16 = unsigned_bitextract_32(15, 0, offset); |
| 2108 |
| 2109 brk(high16); |
| 2110 brk(low16); |
| 2111 } |
| 2112 } |
| 2113 |
| 2114 |
| 2063 // Note: | 2115 // Note: |
| 2064 // Below, a difference in case for the same letter indicates a | 2116 // Below, a difference in case for the same letter indicates a |
| 2065 // negated bit. | 2117 // negated bit. |
| 2066 // If b is 1, then B is 0. | 2118 // If b is 1, then B is 0. |
| 2067 Instr Assembler::ImmFP32(float imm) { | 2119 Instr Assembler::ImmFP32(float imm) { |
| 2068 DCHECK(IsImmFP32(imm)); | 2120 DCHECK(IsImmFP32(imm)); |
| 2069 // bits: aBbb.bbbc.defg.h000.0000.0000.0000.0000 | 2121 // bits: aBbb.bbbc.defg.h000.0000.0000.0000.0000 |
| 2070 uint32_t bits = float_to_rawbits(imm); | 2122 uint32_t bits = float_to_rawbits(imm); |
| 2071 // bit7: a000.0000 | 2123 // bit7: a000.0000 |
| 2072 uint32_t bit7 = ((bits >> 31) & 0x1) << 7; | 2124 uint32_t bit7 = ((bits >> 31) & 0x1) << 7; |
| (...skipping 739 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2812 buffer_ = desc.buffer; | 2864 buffer_ = desc.buffer; |
| 2813 buffer_size_ = desc.buffer_size; | 2865 buffer_size_ = desc.buffer_size; |
| 2814 pc_ = reinterpret_cast<byte*>(pc_) + pc_delta; | 2866 pc_ = reinterpret_cast<byte*>(pc_) + pc_delta; |
| 2815 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta, | 2867 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta, |
| 2816 reloc_info_writer.last_pc() + pc_delta); | 2868 reloc_info_writer.last_pc() + pc_delta); |
| 2817 | 2869 |
| 2818 // None of our relocation types are pc relative pointing outside the code | 2870 // None of our relocation types are pc relative pointing outside the code |
| 2819 // buffer nor pc absolute pointing inside the code buffer, so there is no need | 2871 // buffer nor pc absolute pointing inside the code buffer, so there is no need |
| 2820 // to relocate any emitted relocation entries. | 2872 // to relocate any emitted relocation entries. |
| 2821 | 2873 |
| 2874 // Relocate internal references. |
| 2875 for (auto pos : internal_reference_positions_) { |
| 2876 intptr_t* p = reinterpret_cast<intptr_t*>(buffer_ + pos); |
| 2877 *p += pc_delta; |
| 2878 } |
| 2879 |
| 2822 // Pending relocation entries are also relative, no need to relocate. | 2880 // Pending relocation entries are also relative, no need to relocate. |
| 2823 } | 2881 } |
| 2824 | 2882 |
| 2825 | 2883 |
| 2826 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) { | 2884 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) { |
| 2827 // We do not try to reuse pool constants. | 2885 // We do not try to reuse pool constants. |
| 2828 RelocInfo rinfo(reinterpret_cast<byte*>(pc_), rmode, data, NULL); | 2886 RelocInfo rinfo(reinterpret_cast<byte*>(pc_), rmode, data, NULL); |
| 2829 if (((rmode >= RelocInfo::JS_RETURN) && | 2887 if (((rmode >= RelocInfo::JS_RETURN) && |
| 2830 (rmode <= RelocInfo::DEBUG_BREAK_SLOT)) || | 2888 (rmode <= RelocInfo::DEBUG_BREAK_SLOT)) || |
| 2889 (rmode == RelocInfo::INTERNAL_REFERENCE) || |
| 2831 (rmode == RelocInfo::CONST_POOL) || | 2890 (rmode == RelocInfo::CONST_POOL) || |
| 2832 (rmode == RelocInfo::VENEER_POOL) || | 2891 (rmode == RelocInfo::VENEER_POOL) || |
| 2833 (rmode == RelocInfo::DEOPT_REASON)) { | 2892 (rmode == RelocInfo::DEOPT_REASON)) { |
| 2834 // Adjust code for new modes. | 2893 // Adjust code for new modes. |
| 2835 DCHECK(RelocInfo::IsDebugBreakSlot(rmode) | 2894 DCHECK(RelocInfo::IsDebugBreakSlot(rmode) |
| 2836 || RelocInfo::IsJSReturn(rmode) | 2895 || RelocInfo::IsJSReturn(rmode) |
| 2837 || RelocInfo::IsComment(rmode) | 2896 || RelocInfo::IsComment(rmode) |
| 2838 || RelocInfo::IsDeoptReason(rmode) | 2897 || RelocInfo::IsDeoptReason(rmode) |
| 2839 || RelocInfo::IsPosition(rmode) | 2898 || RelocInfo::IsPosition(rmode) |
| 2899 || RelocInfo::IsInternalReference(rmode) |
| 2840 || RelocInfo::IsConstPool(rmode) | 2900 || RelocInfo::IsConstPool(rmode) |
| 2841 || RelocInfo::IsVeneerPool(rmode)); | 2901 || RelocInfo::IsVeneerPool(rmode)); |
| 2842 // These modes do not need an entry in the constant pool. | 2902 // These modes do not need an entry in the constant pool. |
| 2843 } else { | 2903 } else { |
| 2844 constpool_.RecordEntry(data, rmode); | 2904 constpool_.RecordEntry(data, rmode); |
| 2845 // Make sure the constant pool is not emitted in place of the next | 2905 // Make sure the constant pool is not emitted in place of the next |
| 2846 // instruction for which we just recorded relocation info. | 2906 // instruction for which we just recorded relocation info. |
| 2847 BlockConstPoolFor(1); | 2907 BlockConstPoolFor(1); |
| 2848 } | 2908 } |
| 2849 | 2909 |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3107 movz(scratch, (target_offset >> 16) & 0xFFFF, 16); | 3167 movz(scratch, (target_offset >> 16) & 0xFFFF, 16); |
| 3108 movk(scratch, (target_offset >> 32) & 0xFFFF, 32); | 3168 movk(scratch, (target_offset >> 32) & 0xFFFF, 32); |
| 3109 DCHECK((target_offset >> 48) == 0); | 3169 DCHECK((target_offset >> 48) == 0); |
| 3110 add(rd, rd, scratch); | 3170 add(rd, rd, scratch); |
| 3111 } | 3171 } |
| 3112 | 3172 |
| 3113 | 3173 |
| 3114 } } // namespace v8::internal | 3174 } } // namespace v8::internal |
| 3115 | 3175 |
| 3116 #endif // V8_TARGET_ARCH_ARM64 | 3176 #endif // V8_TARGET_ARCH_ARM64 |
| OLD | NEW |