| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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_ARM64) | 6 #if defined(TARGET_ARCH_ARM64) |
| 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/longjump.h" | 10 #include "vm/longjump.h" |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 258 | 258 |
| 259 | 259 |
| 260 void Assembler::LoadPoolPointer(Register pp) { | 260 void Assembler::LoadPoolPointer(Register pp) { |
| 261 const intptr_t object_pool_pc_dist = | 261 const intptr_t object_pool_pc_dist = |
| 262 Instructions::HeaderSize() - Instructions::object_pool_offset() + | 262 Instructions::HeaderSize() - Instructions::object_pool_offset() + |
| 263 CodeSize(); | 263 CodeSize(); |
| 264 // PP <- Read(PC - object_pool_pc_dist). | 264 // PP <- Read(PC - object_pool_pc_dist). |
| 265 ldr(pp, Address::PC(-object_pool_pc_dist)); | 265 ldr(pp, Address::PC(-object_pool_pc_dist)); |
| 266 | 266 |
| 267 // When in the PP register, the pool pointer is untagged. When we | 267 // When in the PP register, the pool pointer is untagged. When we |
| 268 // push it on the stack with PushPP it is tagged again. PopPP then untags | 268 // push it on the stack with TagAndPushPP it is tagged again. PopAndUntagPP |
| 269 // when restoring from the stack. This will make loading from the object | 269 // then untags when restoring from the stack. This will make loading from the |
| 270 // pool only one instruction for the first 4096 entries. Otherwise, because | 270 // object pool only one instruction for the first 4096 entries. Otherwise, |
| 271 // the offset wouldn't be aligned, it would be only one instruction for the | 271 // because the offset wouldn't be aligned, it would be only one instruction |
| 272 // first 64 entries. | 272 // for the first 64 entries. |
| 273 sub(pp, pp, Operand(kHeapObjectTag)); | 273 sub(pp, pp, Operand(kHeapObjectTag)); |
| 274 } | 274 } |
| 275 | 275 |
| 276 void Assembler::LoadWordFromPoolOffset(Register dst, Register pp, | 276 void Assembler::LoadWordFromPoolOffset(Register dst, Register pp, |
| 277 uint32_t offset) { | 277 uint32_t offset) { |
| 278 ASSERT(dst != pp); | 278 ASSERT(dst != pp); |
| 279 if (Address::CanHoldOffset(offset)) { | 279 if (Address::CanHoldOffset(offset)) { |
| 280 ldr(dst, Address(pp, offset)); | 280 ldr(dst, Address(pp, offset)); |
| 281 } else { | 281 } else { |
| 282 const uint16_t offset_low = Utils::Low16Bits(offset); | 282 const uint16_t offset_low = Utils::Low16Bits(offset); |
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 554 } else if (Operand::CanHold(-imm, kXRegSizeInBits, &op) == | 554 } else if (Operand::CanHold(-imm, kXRegSizeInBits, &op) == |
| 555 Operand::Immediate) { | 555 Operand::Immediate) { |
| 556 cmn(rn, op); | 556 cmn(rn, op); |
| 557 } else { | 557 } else { |
| 558 LoadImmediate(TMP2, imm, pp); | 558 LoadImmediate(TMP2, imm, pp); |
| 559 cmp(rn, Operand(TMP2)); | 559 cmp(rn, Operand(TMP2)); |
| 560 } | 560 } |
| 561 } | 561 } |
| 562 | 562 |
| 563 | 563 |
| 564 void Assembler::LoadFromOffset(Register dest, Register base, int32_t offset) { | 564 void Assembler::LoadFromOffset( |
| 565 Register dest, Register base, int32_t offset, OperandSize sz) { |
| 565 ASSERT(base != TMP2); | 566 ASSERT(base != TMP2); |
| 566 if (Address::CanHoldOffset(offset)) { | 567 if (Address::CanHoldOffset(offset)) { |
| 567 ldr(dest, Address(base, offset)); | 568 ldr(dest, Address(base, offset), sz); |
| 568 } else { | 569 } else { |
| 569 // Since offset is 32-bits, it won't be loaded from the pool. | 570 // Since offset is 32-bits, it won't be loaded from the pool. |
| 570 AddImmediate(TMP2, base, offset, kNoRegister); | 571 AddImmediate(TMP2, base, offset, kNoRegister); |
| 571 ldr(dest, Address(TMP2)); | 572 ldr(dest, Address(TMP2), sz); |
| 572 } | 573 } |
| 573 } | 574 } |
| 574 | 575 |
| 575 | 576 |
| 576 void Assembler::StoreToOffset(Register src, Register base, int32_t offset) { | 577 void Assembler::StoreToOffset( |
| 578 Register src, Register base, int32_t offset, OperandSize sz) { |
| 577 ASSERT(src != TMP2); | 579 ASSERT(src != TMP2); |
| 578 ASSERT(base != TMP2); | 580 ASSERT(base != TMP2); |
| 579 if (Address::CanHoldOffset(offset)) { | 581 if (Address::CanHoldOffset(offset)) { |
| 580 str(src, Address(base, offset)); | 582 str(src, Address(base, offset), sz); |
| 581 } else if (Address::CanHoldOffset(offset, Address::PreIndex)) { | |
| 582 mov(TMP2, base); | |
| 583 str(src, Address(TMP2, offset, Address::PreIndex)); | |
| 584 } else { | 583 } else { |
| 585 // Since offset is 32-bits, it won't be loaded from the pool. | 584 // Since offset is 32-bits, it won't be loaded from the pool. |
| 586 AddImmediate(TMP2, base, offset, kNoRegister); | 585 AddImmediate(TMP2, base, offset, kNoRegister); |
| 587 str(src, Address(TMP2)); | 586 str(src, Address(TMP2), sz); |
| 588 } | 587 } |
| 589 } | 588 } |
| 590 | 589 |
| 591 | 590 |
| 592 // Store into object. | 591 // Store into object. |
| 593 // Preserves object and value registers. | 592 // Preserves object and value registers. |
| 594 void Assembler::StoreIntoObjectFilterNoSmi(Register object, | 593 void Assembler::StoreIntoObjectFilterNoSmi(Register object, |
| 595 Register value, | 594 Register value, |
| 596 Label* no_update) { | 595 Label* no_update) { |
| 597 COMPILE_ASSERT((kNewObjectAlignmentOffset == kWordSize) && | 596 COMPILE_ASSERT((kNewObjectAlignmentOffset == kWordSize) && |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 706 Pop(FP); | 705 Pop(FP); |
| 707 Pop(LR); | 706 Pop(LR); |
| 708 } | 707 } |
| 709 | 708 |
| 710 | 709 |
| 711 void Assembler::EnterDartFrame(intptr_t frame_size) { | 710 void Assembler::EnterDartFrame(intptr_t frame_size) { |
| 712 // Setup the frame. | 711 // Setup the frame. |
| 713 adr(TMP, 0); // TMP gets PC of this instruction. | 712 adr(TMP, 0); // TMP gets PC of this instruction. |
| 714 EnterFrame(0); | 713 EnterFrame(0); |
| 715 Push(TMP); // Save PC Marker. | 714 Push(TMP); // Save PC Marker. |
| 716 PushPP(); // Save PP. | 715 TagAndPushPP(); // Save PP. |
| 717 | 716 |
| 718 // Load the pool pointer. | 717 // Load the pool pointer. |
| 719 LoadPoolPointer(PP); | 718 LoadPoolPointer(PP); |
| 720 | 719 |
| 721 // Reserve space. | 720 // Reserve space. |
| 722 if (frame_size > 0) { | 721 if (frame_size > 0) { |
| 723 sub(SP, SP, Operand(frame_size)); | 722 sub(SP, SP, Operand(frame_size)); |
| 724 } | 723 } |
| 725 } | 724 } |
| 726 | 725 |
| 727 | 726 |
| 728 void Assembler::EnterDartFrameWithInfo(intptr_t frame_size, Register new_pp) { | 727 void Assembler::EnterDartFrameWithInfo(intptr_t frame_size, Register new_pp) { |
| 729 // Setup the frame. | 728 // Setup the frame. |
| 730 adr(TMP, 0); // TMP gets PC of this instruction. | 729 adr(TMP, 0); // TMP gets PC of this instruction. |
| 731 EnterFrame(0); | 730 EnterFrame(0); |
| 732 Push(TMP); // Save PC Marker. | 731 Push(TMP); // Save PC Marker. |
| 733 PushPP(); // Save PP. | 732 TagAndPushPP(); // Save PP. |
| 734 | 733 |
| 735 // Load the pool pointer. | 734 // Load the pool pointer. |
| 736 if (new_pp == kNoRegister) { | 735 if (new_pp == kNoRegister) { |
| 737 LoadPoolPointer(PP); | 736 LoadPoolPointer(PP); |
| 738 } else { | 737 } else { |
| 739 mov(PP, new_pp); | 738 mov(PP, new_pp); |
| 740 } | 739 } |
| 741 | 740 |
| 742 // Reserve space. | 741 // Reserve space. |
| 743 if (frame_size > 0) { | 742 if (frame_size > 0) { |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 811 Pop(FP); | 810 Pop(FP); |
| 812 Pop(LR); | 811 Pop(LR); |
| 813 } | 812 } |
| 814 | 813 |
| 815 | 814 |
| 816 void Assembler::CallRuntime(const RuntimeEntry& entry, | 815 void Assembler::CallRuntime(const RuntimeEntry& entry, |
| 817 intptr_t argument_count) { | 816 intptr_t argument_count) { |
| 818 entry.Call(this, argument_count); | 817 entry.Call(this, argument_count); |
| 819 } | 818 } |
| 820 | 819 |
| 820 |
| 821 void Assembler::EnterStubFrame(bool load_pp) { |
| 822 EnterFrame(0); |
| 823 Push(ZR); // Push 0 in the saved PC area for stub frames. |
| 824 TagAndPushPP(); // Save caller's pool pointer |
| 825 if (load_pp) { |
| 826 LoadPoolPointer(PP); |
| 827 } |
| 828 } |
| 829 |
| 830 |
| 831 void Assembler::LeaveStubFrame() { |
| 832 // Restore and untag PP. |
| 833 LoadFromOffset(PP, FP, kSavedCallerPpSlotFromFp * kWordSize); |
| 834 sub(PP, PP, Operand(kHeapObjectTag)); |
| 835 LeaveFrame(); |
| 836 } |
| 837 |
| 821 } // namespace dart | 838 } // namespace dart |
| 822 | 839 |
| 823 #endif // defined TARGET_ARCH_ARM64 | 840 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |