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