| 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_IA32_H_ | 5 #ifndef VM_ASSEMBLER_IA32_H_ |
| 6 #define VM_ASSEMBLER_IA32_H_ | 6 #define VM_ASSEMBLER_IA32_H_ |
| 7 | 7 |
| 8 #ifndef VM_ASSEMBLER_H_ | 8 #ifndef VM_ASSEMBLER_H_ |
| 9 #error Do not include assembler_ia32.h directly; use assembler.h instead. | 9 #error Do not include assembler_ia32.h directly; use assembler.h instead. |
| 10 #endif | 10 #endif |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 105 length_ = 2; | 105 length_ = 2; |
| 106 } | 106 } |
| 107 | 107 |
| 108 void SetDisp8(int8_t disp) { | 108 void SetDisp8(int8_t disp) { |
| 109 ASSERT(length_ == 1 || length_ == 2); | 109 ASSERT(length_ == 1 || length_ == 2); |
| 110 encoding_[length_++] = static_cast<uint8_t>(disp); | 110 encoding_[length_++] = static_cast<uint8_t>(disp); |
| 111 } | 111 } |
| 112 | 112 |
| 113 void SetDisp32(int32_t disp) { | 113 void SetDisp32(int32_t disp) { |
| 114 ASSERT(length_ == 1 || length_ == 2); | 114 ASSERT(length_ == 1 || length_ == 2); |
| 115 int disp_size = sizeof(disp); | 115 intptr_t disp_size = sizeof(disp); |
| 116 memmove(&encoding_[length_], &disp, disp_size); | 116 memmove(&encoding_[length_], &disp, disp_size); |
| 117 length_ += disp_size; | 117 length_ += disp_size; |
| 118 } | 118 } |
| 119 | 119 |
| 120 private: | 120 private: |
| 121 uint8_t length_; | 121 uint8_t length_; |
| 122 uint8_t encoding_[6]; | 122 uint8_t encoding_[6]; |
| 123 uint8_t padding_; | 123 uint8_t padding_; |
| 124 | 124 |
| 125 explicit Operand(Register reg) { SetModRM(3, reg); } | 125 explicit Operand(Register reg) { SetModRM(3, reg); } |
| 126 | 126 |
| 127 // Get the operand encoding byte at the given index. | 127 // Get the operand encoding byte at the given index. |
| 128 uint8_t encoding_at(int index) const { | 128 uint8_t encoding_at(intptr_t index) const { |
| 129 ASSERT(index >= 0 && index < length_); | 129 ASSERT(index >= 0 && index < length_); |
| 130 return encoding_[index]; | 130 return encoding_[index]; |
| 131 } | 131 } |
| 132 | 132 |
| 133 // Returns whether or not this operand is really the given register in | 133 // Returns whether or not this operand is really the given register in |
| 134 // disguise. Used from the assembler to generate better encodings. | 134 // disguise. Used from the assembler to generate better encodings. |
| 135 bool IsRegister(Register reg) const { | 135 bool IsRegister(Register reg) const { |
| 136 return ((encoding_[0] & 0xF8) == 0xC0) // Addressing mode is register only. | 136 return ((encoding_[0] & 0xF8) == 0xC0) // Addressing mode is register only. |
| 137 && ((encoding_[0] & 0x07) == reg); // Register codes match. | 137 && ((encoding_[0] & 0x07) == reg); // Register codes match. |
| 138 } | 138 } |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 228 } | 228 } |
| 229 | 229 |
| 230 ~Label() { | 230 ~Label() { |
| 231 // Assert if label is being destroyed with unresolved branches pending. | 231 // Assert if label is being destroyed with unresolved branches pending. |
| 232 ASSERT(!IsLinked()); | 232 ASSERT(!IsLinked()); |
| 233 ASSERT(!HasNear()); | 233 ASSERT(!HasNear()); |
| 234 } | 234 } |
| 235 | 235 |
| 236 // Returns the position for bound labels. Cannot be used for unused or linked | 236 // Returns the position for bound labels. Cannot be used for unused or linked |
| 237 // labels. | 237 // labels. |
| 238 int Position() const { | 238 intptr_t Position() const { |
| 239 ASSERT(IsBound()); | 239 ASSERT(IsBound()); |
| 240 return -position_ - kWordSize; | 240 return -position_ - kWordSize; |
| 241 } | 241 } |
| 242 | 242 |
| 243 int LinkPosition() const { | 243 intptr_t LinkPosition() const { |
| 244 ASSERT(IsLinked()); | 244 ASSERT(IsLinked()); |
| 245 return position_ - kWordSize; | 245 return position_ - kWordSize; |
| 246 } | 246 } |
| 247 | 247 |
| 248 int NearPosition() { | 248 intptr_t NearPosition() { |
| 249 ASSERT(HasNear()); | 249 ASSERT(HasNear()); |
| 250 return unresolved_near_positions_[--unresolved_]; | 250 return unresolved_near_positions_[--unresolved_]; |
| 251 } | 251 } |
| 252 | 252 |
| 253 bool IsBound() const { return position_ < 0; } | 253 bool IsBound() const { return position_ < 0; } |
| 254 bool IsUnused() const { return (position_ == 0) && (unresolved_ == 0); } | 254 bool IsUnused() const { return (position_ == 0) && (unresolved_ == 0); } |
| 255 bool IsLinked() const { return position_ > 0; } | 255 bool IsLinked() const { return position_ > 0; } |
| 256 bool HasNear() const { return unresolved_ != 0; } | 256 bool HasNear() const { return unresolved_ != 0; } |
| 257 | 257 |
| 258 private: | 258 private: |
| 259 void BindTo(int position) { | 259 void BindTo(intptr_t position) { |
| 260 ASSERT(!IsBound()); | 260 ASSERT(!IsBound()); |
| 261 ASSERT(!HasNear()); | 261 ASSERT(!HasNear()); |
| 262 position_ = -position - kWordSize; | 262 position_ = -position - kWordSize; |
| 263 ASSERT(IsBound()); | 263 ASSERT(IsBound()); |
| 264 } | 264 } |
| 265 | 265 |
| 266 void LinkTo(int position) { | 266 void LinkTo(intptr_t position) { |
| 267 ASSERT(!IsBound()); | 267 ASSERT(!IsBound()); |
| 268 position_ = position + kWordSize; | 268 position_ = position + kWordSize; |
| 269 ASSERT(IsLinked()); | 269 ASSERT(IsLinked()); |
| 270 } | 270 } |
| 271 | 271 |
| 272 void NearLinkTo(int position) { | 272 void NearLinkTo(intptr_t position) { |
| 273 ASSERT(!IsBound()); | 273 ASSERT(!IsBound()); |
| 274 ASSERT(unresolved_ < kMaxUnresolvedBranches); | 274 ASSERT(unresolved_ < kMaxUnresolvedBranches); |
| 275 unresolved_near_positions_[unresolved_++] = position; | 275 unresolved_near_positions_[unresolved_++] = position; |
| 276 } | 276 } |
| 277 | 277 |
| 278 static const int kMaxUnresolvedBranches = 20; | 278 static const int kMaxUnresolvedBranches = 20; |
| 279 | 279 |
| 280 int position_; | 280 intptr_t position_; |
| 281 int unresolved_; | 281 intptr_t unresolved_; |
| 282 int unresolved_near_positions_[kMaxUnresolvedBranches]; | 282 intptr_t unresolved_near_positions_[kMaxUnresolvedBranches]; |
| 283 | 283 |
| 284 friend class Assembler; | 284 friend class Assembler; |
| 285 DISALLOW_COPY_AND_ASSIGN(Label); | 285 DISALLOW_COPY_AND_ASSIGN(Label); |
| 286 }; | 286 }; |
| 287 | 287 |
| 288 | 288 |
| 289 class CPUFeatures : public AllStatic { | 289 class CPUFeatures : public AllStatic { |
| 290 public: | 290 public: |
| 291 static void InitOnce(); | 291 static void InitOnce(); |
| 292 static bool sse2_supported(); | 292 static bool sse2_supported(); |
| (...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 689 * Misc. functionality | 689 * Misc. functionality |
| 690 */ | 690 */ |
| 691 void SmiTag(Register reg) { | 691 void SmiTag(Register reg) { |
| 692 addl(reg, reg); | 692 addl(reg, reg); |
| 693 } | 693 } |
| 694 | 694 |
| 695 void SmiUntag(Register reg) { | 695 void SmiUntag(Register reg) { |
| 696 sarl(reg, Immediate(kSmiTagSize)); | 696 sarl(reg, Immediate(kSmiTagSize)); |
| 697 } | 697 } |
| 698 | 698 |
| 699 int PreferredLoopAlignment() { return 16; } | 699 intptr_t PreferredLoopAlignment() { return 16; } |
| 700 void Align(int alignment, int offset); | 700 void Align(intptr_t alignment, intptr_t offset); |
| 701 void Bind(Label* label); | 701 void Bind(Label* label); |
| 702 | 702 |
| 703 int CodeSize() const { return buffer_.Size(); } | 703 intptr_t CodeSize() const { return buffer_.Size(); } |
| 704 int prologue_offset() const { return prologue_offset_; } | 704 intptr_t prologue_offset() const { return prologue_offset_; } |
| 705 const ZoneGrowableArray<int>& GetPointerOffsets() const { | 705 const ZoneGrowableArray<intptr_t>& GetPointerOffsets() const { |
| 706 return buffer_.pointer_offsets(); | 706 return buffer_.pointer_offsets(); |
| 707 } | 707 } |
| 708 const GrowableObjectArray& object_pool() const { return object_pool_; } | 708 const GrowableObjectArray& object_pool() const { return object_pool_; } |
| 709 | 709 |
| 710 void FinalizeInstructions(const MemoryRegion& region) { | 710 void FinalizeInstructions(const MemoryRegion& region) { |
| 711 buffer_.FinalizeInstructions(region); | 711 buffer_.FinalizeInstructions(region); |
| 712 } | 712 } |
| 713 | 713 |
| 714 // Set up a Dart frame on entry with a frame pointer and PC information to | 714 // Set up a Dart frame on entry with a frame pointer and PC information to |
| 715 // enable easy access to the RawInstruction object of code corresponding | 715 // enable easy access to the RawInstruction object of code corresponding |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 767 Label* failure, | 767 Label* failure, |
| 768 bool near_jump, | 768 bool near_jump, |
| 769 Register instance_reg); | 769 Register instance_reg); |
| 770 | 770 |
| 771 // Debugging and bringup support. | 771 // Debugging and bringup support. |
| 772 void Stop(const char* message); | 772 void Stop(const char* message); |
| 773 void Unimplemented(const char* message); | 773 void Unimplemented(const char* message); |
| 774 void Untested(const char* message); | 774 void Untested(const char* message); |
| 775 void Unreachable(const char* message); | 775 void Unreachable(const char* message); |
| 776 | 776 |
| 777 static void InitializeMemoryWithBreakpoints(uword data, int length); | 777 static void InitializeMemoryWithBreakpoints(uword data, intptr_t length); |
| 778 | 778 |
| 779 void Comment(const char* format, ...) PRINTF_ATTRIBUTE(2, 3); | 779 void Comment(const char* format, ...) PRINTF_ATTRIBUTE(2, 3); |
| 780 const Code::Comments& GetCodeComments() const; | 780 const Code::Comments& GetCodeComments() const; |
| 781 | 781 |
| 782 static const char* RegisterName(Register reg); | 782 static const char* RegisterName(Register reg); |
| 783 static const char* FpuRegisterName(FpuRegister reg); | 783 static const char* FpuRegisterName(FpuRegister reg); |
| 784 | 784 |
| 785 private: | 785 private: |
| 786 AssemblerBuffer buffer_; | 786 AssemblerBuffer buffer_; |
| 787 GrowableObjectArray& object_pool_; // Object pool is not used on ia32. | 787 GrowableObjectArray& object_pool_; // Object pool is not used on ia32. |
| 788 int prologue_offset_; | 788 intptr_t prologue_offset_; |
| 789 | 789 |
| 790 class CodeComment : public ZoneAllocated { | 790 class CodeComment : public ZoneAllocated { |
| 791 public: | 791 public: |
| 792 CodeComment(intptr_t pc_offset, const String& comment) | 792 CodeComment(intptr_t pc_offset, const String& comment) |
| 793 : pc_offset_(pc_offset), comment_(comment) { } | 793 : pc_offset_(pc_offset), comment_(comment) { } |
| 794 | 794 |
| 795 intptr_t pc_offset() const { return pc_offset_; } | 795 intptr_t pc_offset() const { return pc_offset_; } |
| 796 const String& comment() const { return comment_; } | 796 const String& comment() const { return comment_; } |
| 797 | 797 |
| 798 private: | 798 private: |
| 799 intptr_t pc_offset_; | 799 intptr_t pc_offset_; |
| 800 const String& comment_; | 800 const String& comment_; |
| 801 | 801 |
| 802 DISALLOW_COPY_AND_ASSIGN(CodeComment); | 802 DISALLOW_COPY_AND_ASSIGN(CodeComment); |
| 803 }; | 803 }; |
| 804 | 804 |
| 805 GrowableArray<CodeComment*> comments_; | 805 GrowableArray<CodeComment*> comments_; |
| 806 | 806 |
| 807 inline void EmitUint8(uint8_t value); | 807 inline void EmitUint8(uint8_t value); |
| 808 inline void EmitInt32(int32_t value); | 808 inline void EmitInt32(int32_t value); |
| 809 inline void EmitRegisterOperand(int rm, int reg); | 809 inline void EmitRegisterOperand(int rm, int reg); |
| 810 inline void EmitXmmRegisterOperand(int rm, XmmRegister reg); | 810 inline void EmitXmmRegisterOperand(int rm, XmmRegister reg); |
| 811 inline void EmitFixup(AssemblerFixup* fixup); | 811 inline void EmitFixup(AssemblerFixup* fixup); |
| 812 inline void EmitOperandSizeOverride(); | 812 inline void EmitOperandSizeOverride(); |
| 813 | 813 |
| 814 void EmitOperand(int rm, const Operand& operand); | 814 void EmitOperand(int rm, const Operand& operand); |
| 815 void EmitImmediate(const Immediate& imm); | 815 void EmitImmediate(const Immediate& imm); |
| 816 void EmitComplex(int rm, const Operand& operand, const Immediate& immediate); | 816 void EmitComplex(int rm, const Operand& operand, const Immediate& immediate); |
| 817 void EmitLabel(Label* label, int instruction_size); | 817 void EmitLabel(Label* label, intptr_t instruction_size); |
| 818 void EmitLabelLink(Label* label); | 818 void EmitLabelLink(Label* label); |
| 819 void EmitNearLabelLink(Label* label); | 819 void EmitNearLabelLink(Label* label); |
| 820 | 820 |
| 821 void EmitGenericShift(int rm, Register reg, const Immediate& imm); | 821 void EmitGenericShift(int rm, Register reg, const Immediate& imm); |
| 822 void EmitGenericShift(int rm, const Operand& operand, Register shifter); | 822 void EmitGenericShift(int rm, const Operand& operand, Register shifter); |
| 823 | 823 |
| 824 void StoreIntoObjectFilter(Register object, Register value, Label* no_update); | 824 void StoreIntoObjectFilter(Register object, Register value, Label* no_update); |
| 825 | 825 |
| 826 // Shorter filtering sequence that assumes that value is not a smi. | 826 // Shorter filtering sequence that assumes that value is not a smi. |
| 827 void StoreIntoObjectFilterNoSmi(Register object, | 827 void StoreIntoObjectFilterNoSmi(Register object, |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 859 } | 859 } |
| 860 | 860 |
| 861 | 861 |
| 862 inline void Assembler::EmitOperandSizeOverride() { | 862 inline void Assembler::EmitOperandSizeOverride() { |
| 863 EmitUint8(0x66); | 863 EmitUint8(0x66); |
| 864 } | 864 } |
| 865 | 865 |
| 866 } // namespace dart | 866 } // namespace dart |
| 867 | 867 |
| 868 #endif // VM_ASSEMBLER_IA32_H_ | 868 #endif // VM_ASSEMBLER_IA32_H_ |
| OLD | NEW |