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 #include "vm/globals.h" | 5 #include "vm/globals.h" |
6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
7 | 7 |
8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
9 #include "vm/heap.h" | 9 #include "vm/heap.h" |
10 #include "vm/memory_region.h" | 10 #include "vm/memory_region.h" |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
101 if (StubCode::CallToRuntime_entry() != NULL) { | 101 if (StubCode::CallToRuntime_entry() != NULL) { |
102 FindExternalLabel(&StubCode::CallToRuntimeLabel(), kNotPatchable); | 102 FindExternalLabel(&StubCode::CallToRuntimeLabel(), kNotPatchable); |
103 } else { | 103 } else { |
104 object_pool_.Add(Object::null_object(), Heap::kOld); | 104 object_pool_.Add(Object::null_object(), Heap::kOld); |
105 patchable_pool_entries_.Add(kNotPatchable); | 105 patchable_pool_entries_.Add(kNotPatchable); |
106 } | 106 } |
107 } | 107 } |
108 } | 108 } |
109 | 109 |
110 | 110 |
111 void Assembler::InitializeMemoryWithBreakpoints(uword data, int length) { | 111 void Assembler::InitializeMemoryWithBreakpoints(uword data, intptr_t length) { |
112 memset(reinterpret_cast<void*>(data), Instr::kBreakPointInstruction, length); | 112 memset(reinterpret_cast<void*>(data), Instr::kBreakPointInstruction, length); |
113 } | 113 } |
114 | 114 |
115 | 115 |
116 void Assembler::call(Register reg) { | 116 void Assembler::call(Register reg) { |
117 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 117 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
118 Operand operand(reg); | 118 Operand operand(reg); |
119 EmitOperandREX(2, operand, REX_NONE); | 119 EmitOperandREX(2, operand, REX_NONE); |
120 EmitUint8(0xFF); | 120 EmitUint8(0xFF); |
121 EmitOperand(2, operand); | 121 EmitOperand(2, operand); |
(...skipping 1970 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2092 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 2092 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
2093 EmitUint8(0xF4); | 2093 EmitUint8(0xF4); |
2094 } | 2094 } |
2095 | 2095 |
2096 | 2096 |
2097 void Assembler::j(Condition condition, Label* label, bool near) { | 2097 void Assembler::j(Condition condition, Label* label, bool near) { |
2098 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 2098 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
2099 if (label->IsBound()) { | 2099 if (label->IsBound()) { |
2100 static const int kShortSize = 2; | 2100 static const int kShortSize = 2; |
2101 static const int kLongSize = 6; | 2101 static const int kLongSize = 6; |
2102 int offset = label->Position() - buffer_.Size(); | 2102 intptr_t offset = label->Position() - buffer_.Size(); |
2103 ASSERT(offset <= 0); | 2103 ASSERT(offset <= 0); |
2104 if (Utils::IsInt(8, offset - kShortSize)) { | 2104 if (Utils::IsInt(8, offset - kShortSize)) { |
2105 EmitUint8(0x70 + condition); | 2105 EmitUint8(0x70 + condition); |
2106 EmitUint8((offset - kShortSize) & 0xFF); | 2106 EmitUint8((offset - kShortSize) & 0xFF); |
2107 } else { | 2107 } else { |
2108 EmitUint8(0x0F); | 2108 EmitUint8(0x0F); |
2109 EmitUint8(0x80 + condition); | 2109 EmitUint8(0x80 + condition); |
2110 EmitInt32(offset - kLongSize); | 2110 EmitInt32(offset - kLongSize); |
2111 } | 2111 } |
2112 } else if (near) { | 2112 } else if (near) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2144 EmitUint8(0xFF); | 2144 EmitUint8(0xFF); |
2145 EmitOperand(4, operand); | 2145 EmitOperand(4, operand); |
2146 } | 2146 } |
2147 | 2147 |
2148 | 2148 |
2149 void Assembler::jmp(Label* label, bool near) { | 2149 void Assembler::jmp(Label* label, bool near) { |
2150 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 2150 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
2151 if (label->IsBound()) { | 2151 if (label->IsBound()) { |
2152 static const int kShortSize = 2; | 2152 static const int kShortSize = 2; |
2153 static const int kLongSize = 5; | 2153 static const int kLongSize = 5; |
2154 int offset = label->Position() - buffer_.Size(); | 2154 intptr_t offset = label->Position() - buffer_.Size(); |
2155 ASSERT(offset <= 0); | 2155 ASSERT(offset <= 0); |
2156 if (Utils::IsInt(8, offset - kShortSize)) { | 2156 if (Utils::IsInt(8, offset - kShortSize)) { |
2157 EmitUint8(0xEB); | 2157 EmitUint8(0xEB); |
2158 EmitUint8((offset - kShortSize) & 0xFF); | 2158 EmitUint8((offset - kShortSize) & 0xFF); |
2159 } else { | 2159 } else { |
2160 EmitUint8(0xE9); | 2160 EmitUint8(0xE9); |
2161 EmitInt32(offset - kLongSize); | 2161 EmitInt32(offset - kLongSize); |
2162 } | 2162 } |
2163 } else if (near) { | 2163 } else if (near) { |
2164 EmitUint8(0xEB); | 2164 EmitUint8(0xEB); |
(...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2612 // immediate operands in the test rax instructions. | 2612 // immediate operands in the test rax instructions. |
2613 testl(RAX, Immediate(Utils::Low32Bits(message_address))); | 2613 testl(RAX, Immediate(Utils::Low32Bits(message_address))); |
2614 testl(RAX, Immediate(Utils::High32Bits(message_address))); | 2614 testl(RAX, Immediate(Utils::High32Bits(message_address))); |
2615 } | 2615 } |
2616 // Emit the int3 instruction. | 2616 // Emit the int3 instruction. |
2617 int3(); // Execution can be resumed with the 'cont' command in gdb. | 2617 int3(); // Execution can be resumed with the 'cont' command in gdb. |
2618 } | 2618 } |
2619 | 2619 |
2620 | 2620 |
2621 void Assembler::Bind(Label* label) { | 2621 void Assembler::Bind(Label* label) { |
2622 int bound = buffer_.Size(); | 2622 intptr_t bound = buffer_.Size(); |
2623 ASSERT(!label->IsBound()); // Labels can only be bound once. | 2623 ASSERT(!label->IsBound()); // Labels can only be bound once. |
2624 while (label->IsLinked()) { | 2624 while (label->IsLinked()) { |
2625 int position = label->LinkPosition(); | 2625 intptr_t position = label->LinkPosition(); |
2626 int next = buffer_.Load<int32_t>(position); | 2626 intptr_t next = buffer_.Load<int32_t>(position); |
2627 buffer_.Store<int32_t>(position, bound - (position + 4)); | 2627 buffer_.Store<int32_t>(position, bound - (position + 4)); |
2628 label->position_ = next; | 2628 label->position_ = next; |
2629 } | 2629 } |
2630 while (label->HasNear()) { | 2630 while (label->HasNear()) { |
2631 int position = label->NearPosition(); | 2631 intptr_t position = label->NearPosition(); |
2632 int offset = bound - (position + 1); | 2632 intptr_t offset = bound - (position + 1); |
2633 ASSERT(Utils::IsInt(8, offset)); | 2633 ASSERT(Utils::IsInt(8, offset)); |
2634 buffer_.Store<int8_t>(position, offset); | 2634 buffer_.Store<int8_t>(position, offset); |
2635 } | 2635 } |
2636 label->BindTo(bound); | 2636 label->BindTo(bound); |
2637 } | 2637 } |
2638 | 2638 |
2639 | 2639 |
2640 void Assembler::EnterFrame(intptr_t frame_size) { | 2640 void Assembler::EnterFrame(intptr_t frame_size) { |
2641 if (prologue_offset_ == -1) { | 2641 if (prologue_offset_ == -1) { |
2642 prologue_offset_ = CodeSize(); | 2642 prologue_offset_ = CodeSize(); |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2892 ASSERT(cls.id() != kIllegalCid); | 2892 ASSERT(cls.id() != kIllegalCid); |
2893 tags = RawObject::ClassIdTag::update(cls.id(), tags); | 2893 tags = RawObject::ClassIdTag::update(cls.id(), tags); |
2894 LoadImmediate(FieldAddress(instance_reg, Object::tags_offset()), | 2894 LoadImmediate(FieldAddress(instance_reg, Object::tags_offset()), |
2895 Immediate(tags), pp); | 2895 Immediate(tags), pp); |
2896 } else { | 2896 } else { |
2897 jmp(failure); | 2897 jmp(failure); |
2898 } | 2898 } |
2899 } | 2899 } |
2900 | 2900 |
2901 | 2901 |
2902 void Assembler::Align(int alignment, int offset) { | 2902 void Assembler::Align(int alignment, intptr_t offset) { |
2903 ASSERT(Utils::IsPowerOfTwo(alignment)); | 2903 ASSERT(Utils::IsPowerOfTwo(alignment)); |
2904 int pos = offset + buffer_.GetPosition(); | 2904 intptr_t pos = offset + buffer_.GetPosition(); |
2905 int mod = pos & (alignment - 1); | 2905 int mod = pos & (alignment - 1); |
2906 if (mod == 0) { | 2906 if (mod == 0) { |
2907 return; | 2907 return; |
2908 } | 2908 } |
2909 int bytes_needed = alignment - mod; | 2909 intptr_t bytes_needed = alignment - mod; |
2910 while (bytes_needed > MAX_NOP_SIZE) { | 2910 while (bytes_needed > MAX_NOP_SIZE) { |
2911 nop(MAX_NOP_SIZE); | 2911 nop(MAX_NOP_SIZE); |
2912 bytes_needed -= MAX_NOP_SIZE; | 2912 bytes_needed -= MAX_NOP_SIZE; |
2913 } | 2913 } |
2914 if (bytes_needed) { | 2914 if (bytes_needed) { |
2915 nop(bytes_needed); | 2915 nop(bytes_needed); |
2916 } | 2916 } |
2917 ASSERT(((offset + buffer_.GetPosition()) & (alignment-1)) == 0); | 2917 ASSERT(((offset + buffer_.GetPosition()) & (alignment-1)) == 0); |
2918 } | 2918 } |
2919 | 2919 |
2920 | 2920 |
2921 void Assembler::EmitOperand(int rm, const Operand& operand) { | 2921 void Assembler::EmitOperand(int rm, const Operand& operand) { |
2922 ASSERT(rm >= 0 && rm < 8); | 2922 ASSERT(rm >= 0 && rm < 8); |
2923 const int length = operand.length_; | 2923 const intptr_t length = operand.length_; |
2924 ASSERT(length > 0); | 2924 ASSERT(length > 0); |
2925 // Emit the ModRM byte updated with the given RM value. | 2925 // Emit the ModRM byte updated with the given RM value. |
2926 ASSERT((operand.encoding_[0] & 0x38) == 0); | 2926 ASSERT((operand.encoding_[0] & 0x38) == 0); |
2927 EmitUint8(operand.encoding_[0] + (rm << 3)); | 2927 EmitUint8(operand.encoding_[0] + (rm << 3)); |
2928 // Emit the rest of the encoded operand. | 2928 // Emit the rest of the encoded operand. |
2929 for (int i = 1; i < length; i++) { | 2929 for (intptr_t i = 1; i < length; i++) { |
2930 EmitUint8(operand.encoding_[i]); | 2930 EmitUint8(operand.encoding_[i]); |
2931 } | 2931 } |
2932 } | 2932 } |
2933 | 2933 |
2934 | 2934 |
2935 void Assembler::EmitXmmRegisterOperand(int rm, XmmRegister xmm_reg) { | 2935 void Assembler::EmitXmmRegisterOperand(int rm, XmmRegister xmm_reg) { |
2936 Operand operand; | 2936 Operand operand; |
2937 operand.SetModRM(3, static_cast<Register>(xmm_reg)); | 2937 operand.SetModRM(3, static_cast<Register>(xmm_reg)); |
2938 EmitOperand(rm, operand); | 2938 EmitOperand(rm, operand); |
2939 } | 2939 } |
(...skipping 23 matching lines...) Expand all Loading... |
2963 EmitUint8(0x05 + (rm << 3)); | 2963 EmitUint8(0x05 + (rm << 3)); |
2964 EmitImmediate(immediate); | 2964 EmitImmediate(immediate); |
2965 } else { | 2965 } else { |
2966 EmitUint8(0x81); | 2966 EmitUint8(0x81); |
2967 EmitOperand(rm, operand); | 2967 EmitOperand(rm, operand); |
2968 EmitImmediate(immediate); | 2968 EmitImmediate(immediate); |
2969 } | 2969 } |
2970 } | 2970 } |
2971 | 2971 |
2972 | 2972 |
2973 void Assembler::EmitLabel(Label* label, int instruction_size) { | 2973 void Assembler::EmitLabel(Label* label, intptr_t instruction_size) { |
2974 if (label->IsBound()) { | 2974 if (label->IsBound()) { |
2975 int offset = label->Position() - buffer_.Size(); | 2975 intptr_t offset = label->Position() - buffer_.Size(); |
2976 ASSERT(offset <= 0); | 2976 ASSERT(offset <= 0); |
2977 EmitInt32(offset - instruction_size); | 2977 EmitInt32(offset - instruction_size); |
2978 } else { | 2978 } else { |
2979 EmitLabelLink(label); | 2979 EmitLabelLink(label); |
2980 } | 2980 } |
2981 } | 2981 } |
2982 | 2982 |
2983 | 2983 |
2984 void Assembler::EmitLabelLink(Label* label) { | 2984 void Assembler::EmitLabelLink(Label* label) { |
2985 ASSERT(!label->IsBound()); | 2985 ASSERT(!label->IsBound()); |
2986 int position = buffer_.Size(); | 2986 intptr_t position = buffer_.Size(); |
2987 EmitInt32(label->position_); | 2987 EmitInt32(label->position_); |
2988 label->LinkTo(position); | 2988 label->LinkTo(position); |
2989 } | 2989 } |
2990 | 2990 |
2991 | 2991 |
2992 void Assembler::EmitNearLabelLink(Label* label) { | 2992 void Assembler::EmitNearLabelLink(Label* label) { |
2993 ASSERT(!label->IsBound()); | 2993 ASSERT(!label->IsBound()); |
2994 int position = buffer_.Size(); | 2994 intptr_t position = buffer_.Size(); |
2995 EmitUint8(0); | 2995 EmitUint8(0); |
2996 label->NearLinkTo(position); | 2996 label->NearLinkTo(position); |
2997 } | 2997 } |
2998 | 2998 |
2999 | 2999 |
3000 void Assembler::EmitGenericShift(bool wide, | 3000 void Assembler::EmitGenericShift(bool wide, |
3001 int rm, | 3001 int rm, |
3002 Register reg, | 3002 Register reg, |
3003 const Immediate& imm) { | 3003 const Immediate& imm) { |
3004 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 3004 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3085 | 3085 |
3086 | 3086 |
3087 const char* Assembler::FpuRegisterName(FpuRegister reg) { | 3087 const char* Assembler::FpuRegisterName(FpuRegister reg) { |
3088 ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters)); | 3088 ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters)); |
3089 return xmm_reg_names[reg]; | 3089 return xmm_reg_names[reg]; |
3090 } | 3090 } |
3091 | 3091 |
3092 } // namespace dart | 3092 } // namespace dart |
3093 | 3093 |
3094 #endif // defined TARGET_ARCH_X64 | 3094 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |