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