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" // NOLINT | 5 #include "vm/globals.h" // NOLINT |
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/cpu.h" | 9 #include "vm/cpu.h" |
10 #include "vm/heap.h" | 10 #include "vm/heap.h" |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
74 { // Encode movq(TMP, Immediate(label->address())), but always as imm64. | 74 { // Encode movq(TMP, Immediate(label->address())), but always as imm64. |
75 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 75 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
76 EmitRegisterREX(TMP, REX_W); | 76 EmitRegisterREX(TMP, REX_W); |
77 EmitUint8(0xB8 | (TMP & 7)); | 77 EmitUint8(0xB8 | (TMP & 7)); |
78 EmitInt64(label->address()); | 78 EmitInt64(label->address()); |
79 } | 79 } |
80 call(TMP); | 80 call(TMP); |
81 } | 81 } |
82 | 82 |
83 | 83 |
84 void Assembler::CallPatchable(const ExternalLabel* label) { | 84 void Assembler::CallPatchable(const StubEntry& stub_entry) { |
85 ASSERT(constant_pool_allowed()); | 85 ASSERT(constant_pool_allowed()); |
86 intptr_t call_start = buffer_.GetPosition(); | 86 intptr_t call_start = buffer_.GetPosition(); |
87 const int32_t offset = ObjectPool::element_offset( | 87 const int32_t offset = ObjectPool::element_offset( |
88 object_pool_wrapper_.FindExternalLabel(label, kPatchable)); | 88 object_pool_wrapper_.FindExternalLabel(&stub_entry.label(), kPatchable)); |
89 call(Address::AddressBaseImm32(PP, offset - kHeapObjectTag)); | 89 call(Address::AddressBaseImm32(PP, offset - kHeapObjectTag)); |
90 ASSERT((buffer_.GetPosition() - call_start) == kCallExternalLabelSize); | 90 ASSERT((buffer_.GetPosition() - call_start) == kCallExternalLabelSize); |
91 } | 91 } |
92 | 92 |
93 | 93 |
94 void Assembler::Call(const ExternalLabel* label) { | 94 void Assembler::Call(const StubEntry& stub_entry) { |
95 ASSERT(constant_pool_allowed()); | 95 ASSERT(constant_pool_allowed()); |
96 const int32_t offset = ObjectPool::element_offset( | 96 const int32_t offset = ObjectPool::element_offset( |
97 object_pool_wrapper_.FindExternalLabel(label, kNotPatchable)); | 97 object_pool_wrapper_.FindExternalLabel(&stub_entry.label(), |
| 98 kNotPatchable)); |
98 call(Address::AddressBaseImm32(PP, offset - kHeapObjectTag)); | 99 call(Address::AddressBaseImm32(PP, offset - kHeapObjectTag)); |
99 } | 100 } |
100 | 101 |
101 | 102 |
102 void Assembler::CallPatchable(const StubEntry& stub_entry) { | |
103 const ExternalLabel label(stub_entry.EntryPoint()); | |
104 CallPatchable(&label); | |
105 } | |
106 | |
107 | |
108 void Assembler::Call(const StubEntry& stub_entry) { | |
109 const ExternalLabel label(stub_entry.EntryPoint()); | |
110 Call(&label); | |
111 } | |
112 | |
113 | |
114 void Assembler::pushq(Register reg) { | 103 void Assembler::pushq(Register reg) { |
115 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 104 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
116 EmitRegisterREX(reg, REX_NONE); | 105 EmitRegisterREX(reg, REX_NONE); |
117 EmitUint8(0x50 | (reg & 7)); | 106 EmitUint8(0x50 | (reg & 7)); |
118 } | 107 } |
119 | 108 |
120 | 109 |
121 void Assembler::pushq(const Address& address) { | 110 void Assembler::pushq(const Address& address) { |
122 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 111 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
123 EmitOperandREX(6, address, REX_NONE); | 112 EmitOperandREX(6, address, REX_NONE); |
(...skipping 2413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2537 EmitUint8(0x70 + condition); | 2526 EmitUint8(0x70 + condition); |
2538 EmitNearLabelLink(label); | 2527 EmitNearLabelLink(label); |
2539 } else { | 2528 } else { |
2540 EmitUint8(0x0F); | 2529 EmitUint8(0x0F); |
2541 EmitUint8(0x80 + condition); | 2530 EmitUint8(0x80 + condition); |
2542 EmitLabelLink(label); | 2531 EmitLabelLink(label); |
2543 } | 2532 } |
2544 } | 2533 } |
2545 | 2534 |
2546 | 2535 |
2547 void Assembler::j(Condition condition, const ExternalLabel* label) { | |
2548 Label no_jump; | |
2549 // Negate condition. | |
2550 j(static_cast<Condition>(condition ^ 1), &no_jump, Assembler::kNearJump); | |
2551 jmp(label); | |
2552 Bind(&no_jump); | |
2553 } | |
2554 | |
2555 | |
2556 void Assembler::J(Condition condition, const ExternalLabel* label, | |
2557 Register pp) { | |
2558 Label no_jump; | |
2559 // Negate condition. | |
2560 j(static_cast<Condition>(condition ^ 1), &no_jump, Assembler::kNearJump); | |
2561 Jmp(label, pp); | |
2562 Bind(&no_jump); | |
2563 } | |
2564 | |
2565 | |
2566 void Assembler::J(Condition condition, const StubEntry& stub_entry, | 2536 void Assembler::J(Condition condition, const StubEntry& stub_entry, |
2567 Register pp) { | 2537 Register pp) { |
2568 const ExternalLabel label(stub_entry.EntryPoint()); | 2538 Label no_jump; |
2569 J(condition, &label, pp); | 2539 // Negate condition. |
| 2540 j(static_cast<Condition>(condition ^ 1), &no_jump, Assembler::kNearJump); |
| 2541 Jmp(stub_entry, pp); |
| 2542 Bind(&no_jump); |
2570 } | 2543 } |
2571 | 2544 |
2572 | 2545 |
2573 void Assembler::jmp(Register reg) { | 2546 void Assembler::jmp(Register reg) { |
2574 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 2547 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
2575 Operand operand(reg); | 2548 Operand operand(reg); |
2576 EmitOperandREX(4, operand, REX_NONE); | 2549 EmitOperandREX(4, operand, REX_NONE); |
2577 EmitUint8(0xFF); | 2550 EmitUint8(0xFF); |
2578 EmitOperand(4, operand); | 2551 EmitOperand(4, operand); |
2579 } | 2552 } |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2619 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 2592 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
2620 EmitRegisterREX(TMP, REX_W); | 2593 EmitRegisterREX(TMP, REX_W); |
2621 EmitUint8(0xB8 | (TMP & 7)); | 2594 EmitUint8(0xB8 | (TMP & 7)); |
2622 EmitInt64(label->address()); | 2595 EmitInt64(label->address()); |
2623 } | 2596 } |
2624 jmp(TMP); | 2597 jmp(TMP); |
2625 } | 2598 } |
2626 | 2599 |
2627 | 2600 |
2628 void Assembler::jmp(const StubEntry& stub_entry) { | 2601 void Assembler::jmp(const StubEntry& stub_entry) { |
2629 const ExternalLabel label(stub_entry.EntryPoint()); | 2602 jmp(&stub_entry.label()); |
2630 jmp(&label); | |
2631 } | 2603 } |
2632 | 2604 |
2633 | 2605 |
2634 void Assembler::JmpPatchable(const ExternalLabel* label, Register pp) { | 2606 void Assembler::JmpPatchable(const StubEntry& stub_entry, Register pp) { |
2635 ASSERT((pp != PP) || constant_pool_allowed()); | 2607 ASSERT((pp != PP) || constant_pool_allowed()); |
2636 intptr_t call_start = buffer_.GetPosition(); | 2608 intptr_t call_start = buffer_.GetPosition(); |
2637 const int32_t offset = ObjectPool::element_offset( | 2609 const int32_t offset = ObjectPool::element_offset( |
2638 object_pool_wrapper_.FindExternalLabel(label, kPatchable)); | 2610 object_pool_wrapper_.FindExternalLabel(&stub_entry.label(), kPatchable)); |
2639 // Patchable jumps always use a 32-bit immediate encoding. | 2611 // Patchable jumps always use a 32-bit immediate encoding. |
2640 jmp(Address::AddressBaseImm32(pp, offset - kHeapObjectTag)); | 2612 jmp(Address::AddressBaseImm32(pp, offset - kHeapObjectTag)); |
2641 ASSERT((buffer_.GetPosition() - call_start) == JumpPattern::kLengthInBytes); | 2613 ASSERT((buffer_.GetPosition() - call_start) == JumpPattern::kLengthInBytes); |
2642 } | 2614 } |
2643 | 2615 |
2644 | 2616 |
2645 void Assembler::JmpPatchable(const StubEntry& stub_entry, Register pp) { | 2617 void Assembler::Jmp(const StubEntry& stub_entry, Register pp) { |
2646 const ExternalLabel label(stub_entry.EntryPoint()); | |
2647 JmpPatchable(&label, pp); | |
2648 } | |
2649 | |
2650 | |
2651 void Assembler::Jmp(const ExternalLabel* label, Register pp) { | |
2652 ASSERT((pp != PP) || constant_pool_allowed()); | 2618 ASSERT((pp != PP) || constant_pool_allowed()); |
2653 const int32_t offset = ObjectPool::element_offset( | 2619 const int32_t offset = ObjectPool::element_offset( |
2654 object_pool_wrapper_.FindExternalLabel(label, kNotPatchable)); | 2620 object_pool_wrapper_.FindExternalLabel(&stub_entry.label(), |
| 2621 kNotPatchable)); |
2655 jmp(Address(pp, offset - kHeapObjectTag)); | 2622 jmp(Address(pp, offset - kHeapObjectTag)); |
2656 } | 2623 } |
2657 | 2624 |
2658 | 2625 |
2659 void Assembler::Jmp(const StubEntry& stub_entry, Register pp) { | |
2660 const ExternalLabel label(stub_entry.EntryPoint()); | |
2661 Jmp(&label, pp); | |
2662 } | |
2663 | |
2664 | |
2665 void Assembler::lock() { | 2626 void Assembler::lock() { |
2666 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 2627 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
2667 EmitUint8(0xF0); | 2628 EmitUint8(0xF0); |
2668 } | 2629 } |
2669 | 2630 |
2670 | 2631 |
2671 void Assembler::cmpxchgl(const Address& address, Register reg) { | 2632 void Assembler::cmpxchgl(const Address& address, Register reg) { |
2672 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 2633 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
2673 EmitOperandREX(reg, address, REX_NONE); | 2634 EmitOperandREX(reg, address, REX_NONE); |
2674 EmitUint8(0x0F); | 2635 EmitUint8(0x0F); |
(...skipping 674 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3349 offset += kFpuRegisterSize; | 3310 offset += kFpuRegisterSize; |
3350 } | 3311 } |
3351 } | 3312 } |
3352 ASSERT(offset == (xmm_regs_count * kFpuRegisterSize)); | 3313 ASSERT(offset == (xmm_regs_count * kFpuRegisterSize)); |
3353 AddImmediate(RSP, Immediate(offset)); | 3314 AddImmediate(RSP, Immediate(offset)); |
3354 } | 3315 } |
3355 } | 3316 } |
3356 | 3317 |
3357 | 3318 |
3358 void Assembler::EnterCallRuntimeFrame(intptr_t frame_space) { | 3319 void Assembler::EnterCallRuntimeFrame(intptr_t frame_space) { |
3359 EnterFrame(0); | 3320 EnterStubFrame(); |
3360 | 3321 |
3361 // TODO(vegorov): avoid saving FpuTMP, it is used only as scratch. | 3322 // TODO(vegorov): avoid saving FpuTMP, it is used only as scratch. |
3362 PushRegisters(CallingConventions::kVolatileCpuRegisters, | 3323 PushRegisters(CallingConventions::kVolatileCpuRegisters, |
3363 CallingConventions::kVolatileXmmRegisters); | 3324 CallingConventions::kVolatileXmmRegisters); |
3364 | 3325 |
3365 ReserveAlignedFrameSpace(frame_space); | 3326 ReserveAlignedFrameSpace(frame_space); |
3366 } | 3327 } |
3367 | 3328 |
3368 | 3329 |
3369 void Assembler::LeaveCallRuntimeFrame() { | 3330 void Assembler::LeaveCallRuntimeFrame() { |
3370 // RSP might have been modified to reserve space for arguments | 3331 // RSP might have been modified to reserve space for arguments |
3371 // and ensure proper alignment of the stack frame. | 3332 // and ensure proper alignment of the stack frame. |
3372 // We need to restore it before restoring registers. | 3333 // We need to restore it before restoring registers. |
3373 const intptr_t kPushedCpuRegistersCount = | 3334 const intptr_t kPushedCpuRegistersCount = |
3374 RegisterSet::RegisterCount(CallingConventions::kVolatileCpuRegisters); | 3335 RegisterSet::RegisterCount(CallingConventions::kVolatileCpuRegisters); |
3375 const intptr_t kPushedXmmRegistersCount = | 3336 const intptr_t kPushedXmmRegistersCount = |
3376 RegisterSet::RegisterCount(CallingConventions::kVolatileXmmRegisters); | 3337 RegisterSet::RegisterCount(CallingConventions::kVolatileXmmRegisters); |
3377 const intptr_t kPushedRegistersSize = | 3338 const intptr_t kPushedRegistersSize = |
3378 kPushedCpuRegistersCount * kWordSize + | 3339 kPushedCpuRegistersCount * kWordSize + |
3379 kPushedXmmRegistersCount * kFpuRegisterSize; | 3340 kPushedXmmRegistersCount * kFpuRegisterSize + |
| 3341 2 * kWordSize; // PP, pc marker from EnterStubFrame |
3380 leaq(RSP, Address(RBP, -kPushedRegistersSize)); | 3342 leaq(RSP, Address(RBP, -kPushedRegistersSize)); |
3381 | 3343 |
3382 // TODO(vegorov): avoid saving FpuTMP, it is used only as scratch. | 3344 // TODO(vegorov): avoid saving FpuTMP, it is used only as scratch. |
3383 PopRegisters(CallingConventions::kVolatileCpuRegisters, | 3345 PopRegisters(CallingConventions::kVolatileCpuRegisters, |
3384 CallingConventions::kVolatileXmmRegisters); | 3346 CallingConventions::kVolatileXmmRegisters); |
3385 | 3347 |
3386 leave(); | 3348 LeaveStubFrame(); |
3387 } | 3349 } |
3388 | 3350 |
3389 | 3351 |
3390 void Assembler::CallCFunction(const ExternalLabel* label) { | |
3391 // Reserve shadow space for outgoing arguments. | |
3392 if (CallingConventions::kShadowSpaceBytes != 0) { | |
3393 subq(RSP, Immediate(CallingConventions::kShadowSpaceBytes)); | |
3394 } | |
3395 call(label); | |
3396 } | |
3397 | |
3398 | |
3399 void Assembler::CallCFunction(Register reg) { | 3352 void Assembler::CallCFunction(Register reg) { |
3400 // Reserve shadow space for outgoing arguments. | 3353 // Reserve shadow space for outgoing arguments. |
3401 if (CallingConventions::kShadowSpaceBytes != 0) { | 3354 if (CallingConventions::kShadowSpaceBytes != 0) { |
3402 subq(RSP, Immediate(CallingConventions::kShadowSpaceBytes)); | 3355 subq(RSP, Immediate(CallingConventions::kShadowSpaceBytes)); |
3403 } | 3356 } |
3404 call(reg); | 3357 call(reg); |
3405 } | 3358 } |
3406 | 3359 |
3407 | 3360 |
3408 void Assembler::CallRuntime(const RuntimeEntry& entry, | 3361 void Assembler::CallRuntime(const RuntimeEntry& entry, |
(...skipping 565 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3974 | 3927 |
3975 | 3928 |
3976 const char* Assembler::FpuRegisterName(FpuRegister reg) { | 3929 const char* Assembler::FpuRegisterName(FpuRegister reg) { |
3977 ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters)); | 3930 ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters)); |
3978 return xmm_reg_names[reg]; | 3931 return xmm_reg_names[reg]; |
3979 } | 3932 } |
3980 | 3933 |
3981 } // namespace dart | 3934 } // namespace dart |
3982 | 3935 |
3983 #endif // defined TARGET_ARCH_X64 | 3936 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |