OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #ifndef VM_ASSEMBLER_X64_H_ | 5 #ifndef VM_ASSEMBLER_X64_H_ |
6 #define VM_ASSEMBLER_X64_H_ | 6 #define VM_ASSEMBLER_X64_H_ |
7 | 7 |
8 #ifndef VM_ASSEMBLER_H_ | 8 #ifndef VM_ASSEMBLER_H_ |
9 #error Do not include assembler_x64.h directly; use assembler.h instead. | 9 #error Do not include assembler_x64.h directly; use assembler.h instead. |
10 #endif | 10 #endif |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
137 } | 137 } |
138 | 138 |
139 private: | 139 private: |
140 uint8_t length_; | 140 uint8_t length_; |
141 uint8_t rex_; | 141 uint8_t rex_; |
142 uint8_t encoding_[6]; | 142 uint8_t encoding_[6]; |
143 | 143 |
144 explicit Operand(Register reg) : rex_(REX_NONE) { SetModRM(3, reg); } | 144 explicit Operand(Register reg) : rex_(REX_NONE) { SetModRM(3, reg); } |
145 | 145 |
146 // Get the operand encoding byte at the given index. | 146 // Get the operand encoding byte at the given index. |
147 uint8_t encoding_at(int index) const { | 147 uint8_t encoding_at(intptr_t index) const { |
148 ASSERT(index >= 0 && index < length_); | 148 ASSERT(index >= 0 && index < length_); |
149 return encoding_[index]; | 149 return encoding_[index]; |
150 } | 150 } |
151 | 151 |
152 // Returns whether or not this operand is really the given register in | 152 // Returns whether or not this operand is really the given register in |
153 // disguise. Used from the assembler to generate better encodings. | 153 // disguise. Used from the assembler to generate better encodings. |
154 bool IsRegister(Register reg) const { | 154 bool IsRegister(Register reg) const { |
155 return ((reg > 7 ? 1 : 0) == (rex_ & REX_B)) // REX.B match. | 155 return ((reg > 7 ? 1 : 0) == (rex_ & REX_B)) // REX.B match. |
156 && ((encoding_at(0) & 0xF8) == 0xC0) // Addressing mode is register. | 156 && ((encoding_at(0) & 0xF8) == 0xC0) // Addressing mode is register. |
157 && ((encoding_at(0) & 0x07) == reg); // Register codes match. | 157 && ((encoding_at(0) & 0x07) == reg); // Register codes match. |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
258 } | 258 } |
259 | 259 |
260 ~Label() { | 260 ~Label() { |
261 // Assert if label is being destroyed with unresolved branches pending. | 261 // Assert if label is being destroyed with unresolved branches pending. |
262 ASSERT(!IsLinked()); | 262 ASSERT(!IsLinked()); |
263 ASSERT(!HasNear()); | 263 ASSERT(!HasNear()); |
264 } | 264 } |
265 | 265 |
266 // Returns the position for bound labels. Cannot be used for unused or linked | 266 // Returns the position for bound labels. Cannot be used for unused or linked |
267 // labels. | 267 // labels. |
268 int Position() const { | 268 intptr_t Position() const { |
269 ASSERT(IsBound()); | 269 ASSERT(IsBound()); |
270 return -position_ - kWordSize; | 270 return -position_ - kWordSize; |
271 } | 271 } |
272 | 272 |
273 int LinkPosition() const { | 273 intptr_t LinkPosition() const { |
274 ASSERT(IsLinked()); | 274 ASSERT(IsLinked()); |
275 return position_ - kWordSize; | 275 return position_ - kWordSize; |
276 } | 276 } |
277 | 277 |
278 int NearPosition() { | 278 intptr_t NearPosition() { |
279 ASSERT(HasNear()); | 279 ASSERT(HasNear()); |
280 return unresolved_near_positions_[--unresolved_]; | 280 return unresolved_near_positions_[--unresolved_]; |
281 } | 281 } |
282 | 282 |
283 bool IsBound() const { return position_ < 0; } | 283 bool IsBound() const { return position_ < 0; } |
284 bool IsUnused() const { return (position_ == 0) && (unresolved_ == 0); } | 284 bool IsUnused() const { return (position_ == 0) && (unresolved_ == 0); } |
285 bool IsLinked() const { return position_ > 0; } | 285 bool IsLinked() const { return position_ > 0; } |
286 bool HasNear() const { return unresolved_ != 0; } | 286 bool HasNear() const { return unresolved_ != 0; } |
287 | 287 |
288 private: | 288 private: |
289 void BindTo(int position) { | 289 void BindTo(intptr_t position) { |
290 ASSERT(!IsBound()); | 290 ASSERT(!IsBound()); |
291 ASSERT(!HasNear()); | 291 ASSERT(!HasNear()); |
292 position_ = -position - kWordSize; | 292 position_ = -position - kWordSize; |
293 ASSERT(IsBound()); | 293 ASSERT(IsBound()); |
294 } | 294 } |
295 | 295 |
296 void LinkTo(int position) { | 296 void LinkTo(intptr_t position) { |
297 ASSERT(!IsBound()); | 297 ASSERT(!IsBound()); |
298 position_ = position + kWordSize; | 298 position_ = position + kWordSize; |
299 ASSERT(IsLinked()); | 299 ASSERT(IsLinked()); |
300 } | 300 } |
301 | 301 |
302 void NearLinkTo(int position) { | 302 void NearLinkTo(intptr_t position) { |
303 ASSERT(!IsBound()); | 303 ASSERT(!IsBound()); |
304 ASSERT(unresolved_ < kMaxUnresolvedBranches); | 304 ASSERT(unresolved_ < kMaxUnresolvedBranches); |
305 unresolved_near_positions_[unresolved_++] = position; | 305 unresolved_near_positions_[unresolved_++] = position; |
306 } | 306 } |
307 | 307 |
308 static const int kMaxUnresolvedBranches = 20; | 308 static const int kMaxUnresolvedBranches = 20; |
309 | 309 |
310 int position_; | 310 intptr_t position_; |
311 int unresolved_; | 311 intptr_t unresolved_; |
312 int unresolved_near_positions_[kMaxUnresolvedBranches]; | 312 intptr_t unresolved_near_positions_[kMaxUnresolvedBranches]; |
313 | 313 |
314 friend class Assembler; | 314 friend class Assembler; |
315 DISALLOW_COPY_AND_ASSIGN(Label); | 315 DISALLOW_COPY_AND_ASSIGN(Label); |
316 }; | 316 }; |
317 | 317 |
318 | 318 |
319 class CPUFeatures : public AllStatic { | 319 class CPUFeatures : public AllStatic { |
320 public: | 320 public: |
321 static void InitOnce(); | 321 static void InitOnce(); |
322 // x64 always has at least SSE2. | 322 // x64 always has at least SSE2. |
(...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
743 */ | 743 */ |
744 void SmiTag(Register reg) { | 744 void SmiTag(Register reg) { |
745 addq(reg, reg); | 745 addq(reg, reg); |
746 } | 746 } |
747 | 747 |
748 void SmiUntag(Register reg) { | 748 void SmiUntag(Register reg) { |
749 sarq(reg, Immediate(kSmiTagSize)); | 749 sarq(reg, Immediate(kSmiTagSize)); |
750 } | 750 } |
751 | 751 |
752 int PreferredLoopAlignment() { return 16; } | 752 int PreferredLoopAlignment() { return 16; } |
753 void Align(int alignment, int offset); | 753 void Align(int alignment, intptr_t offset); |
754 void Bind(Label* label); | 754 void Bind(Label* label); |
755 | 755 |
756 void Comment(const char* format, ...) PRINTF_ATTRIBUTE(2, 3); | 756 void Comment(const char* format, ...) PRINTF_ATTRIBUTE(2, 3); |
757 const Code::Comments& GetCodeComments() const; | 757 const Code::Comments& GetCodeComments() const; |
758 | 758 |
759 int CodeSize() const { return buffer_.Size(); } | 759 intptr_t CodeSize() const { return buffer_.Size(); } |
760 int prologue_offset() const { return prologue_offset_; } | 760 intptr_t prologue_offset() const { return prologue_offset_; } |
761 const ZoneGrowableArray<int>& GetPointerOffsets() const { | 761 const ZoneGrowableArray<intptr_t>& GetPointerOffsets() const { |
762 return buffer_.pointer_offsets(); | 762 return buffer_.pointer_offsets(); |
763 } | 763 } |
764 const GrowableObjectArray& object_pool() const { return object_pool_; } | 764 const GrowableObjectArray& object_pool() const { return object_pool_; } |
765 | 765 |
766 void FinalizeInstructions(const MemoryRegion& region) { | 766 void FinalizeInstructions(const MemoryRegion& region) { |
767 buffer_.FinalizeInstructions(region); | 767 buffer_.FinalizeInstructions(region); |
768 } | 768 } |
769 | 769 |
770 void LoadPoolPointer(Register pp); | 770 void LoadPoolPointer(Register pp); |
771 | 771 |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
834 bool near_jump, | 834 bool near_jump, |
835 Register instance_reg, | 835 Register instance_reg, |
836 Register pp); | 836 Register pp); |
837 | 837 |
838 // Debugging and bringup support. | 838 // Debugging and bringup support. |
839 void Stop(const char* message); | 839 void Stop(const char* message); |
840 void Unimplemented(const char* message); | 840 void Unimplemented(const char* message); |
841 void Untested(const char* message); | 841 void Untested(const char* message); |
842 void Unreachable(const char* message); | 842 void Unreachable(const char* message); |
843 | 843 |
844 static void InitializeMemoryWithBreakpoints(uword data, int length); | 844 static void InitializeMemoryWithBreakpoints(uword data, intptr_t length); |
845 | 845 |
846 static const char* RegisterName(Register reg); | 846 static const char* RegisterName(Register reg); |
847 | 847 |
848 static const char* FpuRegisterName(FpuRegister reg); | 848 static const char* FpuRegisterName(FpuRegister reg); |
849 | 849 |
850 private: | 850 private: |
851 AssemblerBuffer buffer_; | 851 AssemblerBuffer buffer_; |
852 | 852 |
853 // Objects and jump targets. | 853 // Objects and jump targets. |
854 GrowableObjectArray& object_pool_; | 854 GrowableObjectArray& object_pool_; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
890 } | 890 } |
891 | 891 |
892 private: | 892 private: |
893 Key key_; | 893 Key key_; |
894 Value value_; | 894 Value value_; |
895 }; | 895 }; |
896 | 896 |
897 // Hashmap for fast lookup in object pool. | 897 // Hashmap for fast lookup in object pool. |
898 DirectChainedHashMap<ObjIndexPair> object_pool_index_table_; | 898 DirectChainedHashMap<ObjIndexPair> object_pool_index_table_; |
899 | 899 |
900 int prologue_offset_; | 900 intptr_t prologue_offset_; |
901 | 901 |
902 class CodeComment : public ZoneAllocated { | 902 class CodeComment : public ZoneAllocated { |
903 public: | 903 public: |
904 CodeComment(intptr_t pc_offset, const String& comment) | 904 CodeComment(intptr_t pc_offset, const String& comment) |
905 : pc_offset_(pc_offset), comment_(comment) { } | 905 : pc_offset_(pc_offset), comment_(comment) { } |
906 | 906 |
907 intptr_t pc_offset() const { return pc_offset_; } | 907 intptr_t pc_offset() const { return pc_offset_; } |
908 const String& comment() const { return comment_; } | 908 const String& comment() const { return comment_; } |
909 | 909 |
910 private: | 910 private: |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
945 uint8_t rex = REX_NONE); | 945 uint8_t rex = REX_NONE); |
946 inline void EmitREX_RB(XmmRegister reg, | 946 inline void EmitREX_RB(XmmRegister reg, |
947 Register base, | 947 Register base, |
948 uint8_t rex = REX_NONE); | 948 uint8_t rex = REX_NONE); |
949 inline void EmitREX_RB(Register reg, | 949 inline void EmitREX_RB(Register reg, |
950 XmmRegister base, | 950 XmmRegister base, |
951 uint8_t rex = REX_NONE); | 951 uint8_t rex = REX_NONE); |
952 void EmitOperand(int rm, const Operand& operand); | 952 void EmitOperand(int rm, const Operand& operand); |
953 void EmitImmediate(const Immediate& imm); | 953 void EmitImmediate(const Immediate& imm); |
954 void EmitComplex(int rm, const Operand& operand, const Immediate& immediate); | 954 void EmitComplex(int rm, const Operand& operand, const Immediate& immediate); |
955 void EmitLabel(Label* label, int instruction_size); | 955 void EmitLabel(Label* label, intptr_t instruction_size); |
956 void EmitLabelLink(Label* label); | 956 void EmitLabelLink(Label* label); |
957 void EmitNearLabelLink(Label* label); | 957 void EmitNearLabelLink(Label* label); |
958 | 958 |
959 void EmitGenericShift(bool wide, int rm, Register reg, const Immediate& imm); | 959 void EmitGenericShift(bool wide, int rm, Register reg, const Immediate& imm); |
960 void EmitGenericShift(bool wide, int rm, Register operand, Register shifter); | 960 void EmitGenericShift(bool wide, int rm, Register operand, Register shifter); |
961 | 961 |
962 void StoreIntoObjectFilter(Register object, Register value, Label* no_update); | 962 void StoreIntoObjectFilter(Register object, Register value, Label* no_update); |
963 | 963 |
964 // Shorter filtering sequence that assumes that value is not a smi. | 964 // Shorter filtering sequence that assumes that value is not a smi. |
965 void StoreIntoObjectFilterNoSmi(Register object, | 965 void StoreIntoObjectFilterNoSmi(Register object, |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1042 } | 1042 } |
1043 | 1043 |
1044 | 1044 |
1045 inline void Assembler::EmitOperandSizeOverride() { | 1045 inline void Assembler::EmitOperandSizeOverride() { |
1046 EmitUint8(0x66); | 1046 EmitUint8(0x66); |
1047 } | 1047 } |
1048 | 1048 |
1049 } // namespace dart | 1049 } // namespace dart |
1050 | 1050 |
1051 #endif // VM_ASSEMBLER_X64_H_ | 1051 #endif // VM_ASSEMBLER_X64_H_ |
OLD | NEW |