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