| 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 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 394 ldr(dst, Address(pp, offset)); | 394 ldr(dst, Address(pp, offset)); |
| 395 } else if (Operand::CanHold(upper20, kXRegSizeInBits, &op) == | 395 } else if (Operand::CanHold(upper20, kXRegSizeInBits, &op) == |
| 396 Operand::Immediate) { | 396 Operand::Immediate) { |
| 397 const uint32_t lower12 = offset & 0x00000fff; | 397 const uint32_t lower12 = offset & 0x00000fff; |
| 398 ASSERT(Address::CanHoldOffset(lower12)); | 398 ASSERT(Address::CanHoldOffset(lower12)); |
| 399 add(dst, pp, op); | 399 add(dst, pp, op); |
| 400 ldr(dst, Address(dst, lower12)); | 400 ldr(dst, Address(dst, lower12)); |
| 401 } else { | 401 } else { |
| 402 const uint16_t offset_low = Utils::Low16Bits(offset); | 402 const uint16_t offset_low = Utils::Low16Bits(offset); |
| 403 const uint16_t offset_high = Utils::High16Bits(offset); | 403 const uint16_t offset_high = Utils::High16Bits(offset); |
| 404 movz(dst, offset_low, 0); | 404 movz(dst, Immediate(offset_low), 0); |
| 405 if (offset_high != 0) { | 405 if (offset_high != 0) { |
| 406 movk(dst, offset_high, 1); | 406 movk(dst, Immediate(offset_high), 1); |
| 407 } | 407 } |
| 408 ldr(dst, Address(pp, dst)); | 408 ldr(dst, Address(pp, dst)); |
| 409 } | 409 } |
| 410 } | 410 } |
| 411 | 411 |
| 412 | 412 |
| 413 void Assembler::LoadWordFromPoolOffsetFixed(Register dst, Register pp, | 413 void Assembler::LoadWordFromPoolOffsetFixed(Register dst, Register pp, |
| 414 uint32_t offset) { | 414 uint32_t offset) { |
| 415 ASSERT(dst != pp); | 415 ASSERT(dst != pp); |
| 416 Operand op; | 416 Operand op; |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 588 void Assembler::LoadDecodableImmediate(Register reg, int64_t imm, Register pp) { | 588 void Assembler::LoadDecodableImmediate(Register reg, int64_t imm, Register pp) { |
| 589 if ((pp != kNoPP) && | 589 if ((pp != kNoPP) && |
| 590 (Isolate::Current() != Dart::vm_isolate()) && | 590 (Isolate::Current() != Dart::vm_isolate()) && |
| 591 allow_constant_pool()) { | 591 allow_constant_pool()) { |
| 592 int64_t val_smi_tag = imm & kSmiTagMask; | 592 int64_t val_smi_tag = imm & kSmiTagMask; |
| 593 imm &= ~kSmiTagMask; // Mask off the tag bits. | 593 imm &= ~kSmiTagMask; // Mask off the tag bits. |
| 594 const int32_t offset = Array::element_offset(FindImmediate(imm)); | 594 const int32_t offset = Array::element_offset(FindImmediate(imm)); |
| 595 LoadWordFromPoolOffset(reg, pp, offset); | 595 LoadWordFromPoolOffset(reg, pp, offset); |
| 596 if (val_smi_tag != 0) { | 596 if (val_smi_tag != 0) { |
| 597 // Add back the tag bits. | 597 // Add back the tag bits. |
| 598 orri(reg, reg, val_smi_tag); | 598 orri(reg, reg, Immediate(val_smi_tag)); |
| 599 } | 599 } |
| 600 } else { | 600 } else { |
| 601 // TODO(zra): Since this sequence only needs to be decodable, it can be | 601 // TODO(zra): Since this sequence only needs to be decodable, it can be |
| 602 // of variable length. | 602 // of variable length. |
| 603 LoadImmediateFixed(reg, imm); | 603 LoadImmediateFixed(reg, imm); |
| 604 } | 604 } |
| 605 } | 605 } |
| 606 | 606 |
| 607 | 607 |
| 608 void Assembler::LoadImmediateFixed(Register reg, int64_t imm) { | 608 void Assembler::LoadImmediateFixed(Register reg, int64_t imm) { |
| 609 const uint32_t w0 = Utils::Low32Bits(imm); | 609 const uint32_t w0 = Utils::Low32Bits(imm); |
| 610 const uint32_t w1 = Utils::High32Bits(imm); | 610 const uint32_t w1 = Utils::High32Bits(imm); |
| 611 const uint16_t h0 = Utils::Low16Bits(w0); | 611 const uint16_t h0 = Utils::Low16Bits(w0); |
| 612 const uint16_t h1 = Utils::High16Bits(w0); | 612 const uint16_t h1 = Utils::High16Bits(w0); |
| 613 const uint16_t h2 = Utils::Low16Bits(w1); | 613 const uint16_t h2 = Utils::Low16Bits(w1); |
| 614 const uint16_t h3 = Utils::High16Bits(w1); | 614 const uint16_t h3 = Utils::High16Bits(w1); |
| 615 movz(reg, h0, 0); | 615 movz(reg, Immediate(h0), 0); |
| 616 movk(reg, h1, 1); | 616 movk(reg, Immediate(h1), 1); |
| 617 movk(reg, h2, 2); | 617 movk(reg, Immediate(h2), 2); |
| 618 movk(reg, h3, 3); | 618 movk(reg, Immediate(h3), 3); |
| 619 } | 619 } |
| 620 | 620 |
| 621 | 621 |
| 622 void Assembler::LoadImmediate(Register reg, int64_t imm, Register pp) { | 622 void Assembler::LoadImmediate(Register reg, int64_t imm, Register pp) { |
| 623 Comment("LoadImmediate"); | 623 Comment("LoadImmediate"); |
| 624 if (CanLoadImmediateFromPool(imm, pp)) { | 624 if (CanLoadImmediateFromPool(imm, pp)) { |
| 625 // It's a 64-bit constant and we're not in the VM isolate, so load from | 625 // It's a 64-bit constant and we're not in the VM isolate, so load from |
| 626 // object pool. | 626 // object pool. |
| 627 // Save the bits that must be masked-off for the SmiTag | 627 // Save the bits that must be masked-off for the SmiTag |
| 628 int64_t val_smi_tag = imm & kSmiTagMask; | 628 int64_t val_smi_tag = imm & kSmiTagMask; |
| 629 imm &= ~kSmiTagMask; // Mask off the tag bits. | 629 imm &= ~kSmiTagMask; // Mask off the tag bits. |
| 630 const int32_t offset = Array::element_offset(FindImmediate(imm)); | 630 const int32_t offset = Array::element_offset(FindImmediate(imm)); |
| 631 LoadWordFromPoolOffset(reg, pp, offset); | 631 LoadWordFromPoolOffset(reg, pp, offset); |
| 632 if (val_smi_tag != 0) { | 632 if (val_smi_tag != 0) { |
| 633 // Add back the tag bits. | 633 // Add back the tag bits. |
| 634 orri(reg, reg, val_smi_tag); | 634 orri(reg, reg, Immediate(val_smi_tag)); |
| 635 } | 635 } |
| 636 } else { | 636 } else { |
| 637 // 0. Is it 0? | 637 // 0. Is it 0? |
| 638 if (imm == 0) { | 638 if (imm == 0) { |
| 639 movz(reg, 0, 0); | 639 movz(reg, Immediate(0), 0); |
| 640 return; | 640 return; |
| 641 } | 641 } |
| 642 | 642 |
| 643 // 1. Can we use one orri operation? | 643 // 1. Can we use one orri operation? |
| 644 Operand op; | 644 Operand op; |
| 645 Operand::OperandType ot; | 645 Operand::OperandType ot; |
| 646 ot = Operand::CanHold(imm, kXRegSizeInBits, &op); | 646 ot = Operand::CanHold(imm, kXRegSizeInBits, &op); |
| 647 if (ot == Operand::BitfieldImm) { | 647 if (ot == Operand::BitfieldImm) { |
| 648 orri(reg, ZR, imm); | 648 orri(reg, ZR, Immediate(imm)); |
| 649 return; | 649 return; |
| 650 } | 650 } |
| 651 | 651 |
| 652 // 2. Fall back on movz, movk, movn. | 652 // 2. Fall back on movz, movk, movn. |
| 653 const uint32_t w0 = Utils::Low32Bits(imm); | 653 const uint32_t w0 = Utils::Low32Bits(imm); |
| 654 const uint32_t w1 = Utils::High32Bits(imm); | 654 const uint32_t w1 = Utils::High32Bits(imm); |
| 655 const uint16_t h0 = Utils::Low16Bits(w0); | 655 const uint16_t h0 = Utils::Low16Bits(w0); |
| 656 const uint16_t h1 = Utils::High16Bits(w0); | 656 const uint16_t h1 = Utils::High16Bits(w0); |
| 657 const uint16_t h2 = Utils::Low16Bits(w1); | 657 const uint16_t h2 = Utils::Low16Bits(w1); |
| 658 const uint16_t h3 = Utils::High16Bits(w1); | 658 const uint16_t h3 = Utils::High16Bits(w1); |
| 659 | 659 |
| 660 // Special case for w1 == 0xffffffff | 660 // Special case for w1 == 0xffffffff |
| 661 if (w1 == 0xffffffff) { | 661 if (w1 == 0xffffffff) { |
| 662 if (h1 == 0xffff) { | 662 if (h1 == 0xffff) { |
| 663 movn(reg, ~h0, 0); | 663 movn(reg, Immediate(~h0), 0); |
| 664 } else { | 664 } else { |
| 665 movn(reg, ~h1, 1); | 665 movn(reg, Immediate(~h1), 1); |
| 666 movk(reg, h0, 0); | 666 movk(reg, Immediate(h0), 0); |
| 667 } | 667 } |
| 668 return; | 668 return; |
| 669 } | 669 } |
| 670 | 670 |
| 671 // Special case for h3 == 0xffff | 671 // Special case for h3 == 0xffff |
| 672 if (h3 == 0xffff) { | 672 if (h3 == 0xffff) { |
| 673 // We know h2 != 0xffff. | 673 // We know h2 != 0xffff. |
| 674 movn(reg, ~h2, 2); | 674 movn(reg, Immediate(~h2), 2); |
| 675 if (h1 != 0xffff) { | 675 if (h1 != 0xffff) { |
| 676 movk(reg, h1, 1); | 676 movk(reg, Immediate(h1), 1); |
| 677 } | 677 } |
| 678 if (h0 != 0xffff) { | 678 if (h0 != 0xffff) { |
| 679 movk(reg, h0, 0); | 679 movk(reg, Immediate(h0), 0); |
| 680 } | 680 } |
| 681 return; | 681 return; |
| 682 } | 682 } |
| 683 | 683 |
| 684 bool initialized = false; | 684 bool initialized = false; |
| 685 if (h0 != 0) { | 685 if (h0 != 0) { |
| 686 movz(reg, h0, 0); | 686 movz(reg, Immediate(h0), 0); |
| 687 initialized = true; | 687 initialized = true; |
| 688 } | 688 } |
| 689 if (h1 != 0) { | 689 if (h1 != 0) { |
| 690 if (initialized) { | 690 if (initialized) { |
| 691 movk(reg, h1, 1); | 691 movk(reg, Immediate(h1), 1); |
| 692 } else { | 692 } else { |
| 693 movz(reg, h1, 1); | 693 movz(reg, Immediate(h1), 1); |
| 694 initialized = true; | 694 initialized = true; |
| 695 } | 695 } |
| 696 } | 696 } |
| 697 if (h2 != 0) { | 697 if (h2 != 0) { |
| 698 if (initialized) { | 698 if (initialized) { |
| 699 movk(reg, h2, 2); | 699 movk(reg, Immediate(h2), 2); |
| 700 } else { | 700 } else { |
| 701 movz(reg, h2, 2); | 701 movz(reg, Immediate(h2), 2); |
| 702 initialized = true; | 702 initialized = true; |
| 703 } | 703 } |
| 704 } | 704 } |
| 705 if (h3 != 0) { | 705 if (h3 != 0) { |
| 706 if (initialized) { | 706 if (initialized) { |
| 707 movk(reg, h3, 3); | 707 movk(reg, Immediate(h3), 3); |
| 708 } else { | 708 } else { |
| 709 movz(reg, h3, 3); | 709 movz(reg, Immediate(h3), 3); |
| 710 } | 710 } |
| 711 } | 711 } |
| 712 } | 712 } |
| 713 } | 713 } |
| 714 | 714 |
| 715 | 715 |
| 716 void Assembler::LoadDImmediate(VRegister vd, double immd, Register pp) { | 716 void Assembler::LoadDImmediate(VRegister vd, double immd, Register pp) { |
| 717 if (!fmovdi(vd, immd)) { | 717 if (!fmovdi(vd, immd)) { |
| 718 int64_t imm = bit_cast<int64_t, double>(immd); | 718 int64_t imm = bit_cast<int64_t, double>(immd); |
| 719 LoadImmediate(TMP, imm, pp); | 719 LoadImmediate(TMP, imm, pp); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 780 LoadImmediate(TMP2, imm, pp); | 780 LoadImmediate(TMP2, imm, pp); |
| 781 subs(dest, rn, Operand(TMP2)); | 781 subs(dest, rn, Operand(TMP2)); |
| 782 } | 782 } |
| 783 } | 783 } |
| 784 | 784 |
| 785 | 785 |
| 786 void Assembler::AndImmediate( | 786 void Assembler::AndImmediate( |
| 787 Register rd, Register rn, int64_t imm, Register pp) { | 787 Register rd, Register rn, int64_t imm, Register pp) { |
| 788 Operand imm_op; | 788 Operand imm_op; |
| 789 if (Operand::IsImmLogical(imm, kXRegSizeInBits, &imm_op)) { | 789 if (Operand::IsImmLogical(imm, kXRegSizeInBits, &imm_op)) { |
| 790 andi(rd, rn, imm); | 790 andi(rd, rn, Immediate(imm)); |
| 791 } else { | 791 } else { |
| 792 LoadImmediate(TMP, imm, pp); | 792 LoadImmediate(TMP, imm, pp); |
| 793 and_(rd, rn, Operand(TMP)); | 793 and_(rd, rn, Operand(TMP)); |
| 794 } | 794 } |
| 795 } | 795 } |
| 796 | 796 |
| 797 | 797 |
| 798 void Assembler::OrImmediate( | 798 void Assembler::OrImmediate( |
| 799 Register rd, Register rn, int64_t imm, Register pp) { | 799 Register rd, Register rn, int64_t imm, Register pp) { |
| 800 Operand imm_op; | 800 Operand imm_op; |
| 801 if (Operand::IsImmLogical(imm, kXRegSizeInBits, &imm_op)) { | 801 if (Operand::IsImmLogical(imm, kXRegSizeInBits, &imm_op)) { |
| 802 orri(rd, rn, imm); | 802 orri(rd, rn, Immediate(imm)); |
| 803 } else { | 803 } else { |
| 804 LoadImmediate(TMP, imm, pp); | 804 LoadImmediate(TMP, imm, pp); |
| 805 orr(rd, rn, Operand(TMP)); | 805 orr(rd, rn, Operand(TMP)); |
| 806 } | 806 } |
| 807 } | 807 } |
| 808 | 808 |
| 809 | 809 |
| 810 void Assembler::XorImmediate( | 810 void Assembler::XorImmediate( |
| 811 Register rd, Register rn, int64_t imm, Register pp) { | 811 Register rd, Register rn, int64_t imm, Register pp) { |
| 812 Operand imm_op; | 812 Operand imm_op; |
| 813 if (Operand::IsImmLogical(imm, kXRegSizeInBits, &imm_op)) { | 813 if (Operand::IsImmLogical(imm, kXRegSizeInBits, &imm_op)) { |
| 814 eori(rd, rn, imm); | 814 eori(rd, rn, Immediate(imm)); |
| 815 } else { | 815 } else { |
| 816 LoadImmediate(TMP, imm, pp); | 816 LoadImmediate(TMP, imm, pp); |
| 817 eor(rd, rn, Operand(TMP)); | 817 eor(rd, rn, Operand(TMP)); |
| 818 } | 818 } |
| 819 } | 819 } |
| 820 | 820 |
| 821 | 821 |
| 822 void Assembler::TestImmediate(Register rn, int64_t imm, Register pp) { | 822 void Assembler::TestImmediate(Register rn, int64_t imm, Register pp) { |
| 823 Operand imm_op; | 823 Operand imm_op; |
| 824 if (Operand::IsImmLogical(imm, kXRegSizeInBits, &imm_op)) { | 824 if (Operand::IsImmLogical(imm, kXRegSizeInBits, &imm_op)) { |
| 825 tsti(rn, imm); | 825 tsti(rn, Immediate(imm)); |
| 826 } else { | 826 } else { |
| 827 LoadImmediate(TMP, imm, pp); | 827 LoadImmediate(TMP, imm, pp); |
| 828 tst(rn, Operand(TMP)); | 828 tst(rn, Operand(TMP)); |
| 829 } | 829 } |
| 830 } | 830 } |
| 831 | 831 |
| 832 | 832 |
| 833 void Assembler::CompareImmediate(Register rn, int64_t imm, Register pp) { | 833 void Assembler::CompareImmediate(Register rn, int64_t imm, Register pp) { |
| 834 Operand op; | 834 Operand op; |
| 835 if (Operand::CanHold(imm, kXRegSizeInBits, &op) == Operand::Immediate) { | 835 if (Operand::CanHold(imm, kXRegSizeInBits, &op) == Operand::Immediate) { |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 957 Register value, | 957 Register value, |
| 958 Label* no_update) { | 958 Label* no_update) { |
| 959 COMPILE_ASSERT((kNewObjectAlignmentOffset == kWordSize) && | 959 COMPILE_ASSERT((kNewObjectAlignmentOffset == kWordSize) && |
| 960 (kOldObjectAlignmentOffset == 0)); | 960 (kOldObjectAlignmentOffset == 0)); |
| 961 | 961 |
| 962 // Write-barrier triggers if the value is in the new space (has bit set) and | 962 // Write-barrier triggers if the value is in the new space (has bit set) and |
| 963 // the object is in the old space (has bit cleared). | 963 // the object is in the old space (has bit cleared). |
| 964 // To check that, we compute value & ~object and skip the write barrier | 964 // To check that, we compute value & ~object and skip the write barrier |
| 965 // if the bit is not set. We can't destroy the object. | 965 // if the bit is not set. We can't destroy the object. |
| 966 bic(TMP, value, Operand(object)); | 966 bic(TMP, value, Operand(object)); |
| 967 tsti(TMP, kNewObjectAlignmentOffset); | 967 tsti(TMP, Immediate(kNewObjectAlignmentOffset)); |
| 968 b(no_update, EQ); | 968 b(no_update, EQ); |
| 969 } | 969 } |
| 970 | 970 |
| 971 | 971 |
| 972 // Preserves object and value registers. | 972 // Preserves object and value registers. |
| 973 void Assembler::StoreIntoObjectFilter(Register object, | 973 void Assembler::StoreIntoObjectFilter(Register object, |
| 974 Register value, | 974 Register value, |
| 975 Label* no_update) { | 975 Label* no_update) { |
| 976 // For the value we are only interested in the new/old bit and the tag bit. | 976 // For the value we are only interested in the new/old bit and the tag bit. |
| 977 // And the new bit with the tag bit. The resulting bit will be 0 for a Smi. | 977 // And the new bit with the tag bit. The resulting bit will be 0 for a Smi. |
| 978 and_(TMP, value, Operand(value, LSL, kObjectAlignmentLog2 - 1)); | 978 and_(TMP, value, Operand(value, LSL, kObjectAlignmentLog2 - 1)); |
| 979 // And the result with the negated space bit of the object. | 979 // And the result with the negated space bit of the object. |
| 980 bic(TMP, TMP, Operand(object)); | 980 bic(TMP, TMP, Operand(object)); |
| 981 tsti(TMP, kNewObjectAlignmentOffset); | 981 tsti(TMP, Immediate(kNewObjectAlignmentOffset)); |
| 982 b(no_update, EQ); | 982 b(no_update, EQ); |
| 983 } | 983 } |
| 984 | 984 |
| 985 | 985 |
| 986 void Assembler::StoreIntoObjectOffset(Register object, | 986 void Assembler::StoreIntoObjectOffset(Register object, |
| 987 int32_t offset, | 987 int32_t offset, |
| 988 Register value, | 988 Register value, |
| 989 Register pp, | 989 Register pp, |
| 990 bool can_value_be_smi) { | 990 bool can_value_be_smi) { |
| 991 if (Address::CanHoldOffset(offset - kHeapObjectTag)) { | 991 if (Address::CanHoldOffset(offset - kHeapObjectTag)) { |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1111 LoadClassId(TMP, object, pp); | 1111 LoadClassId(TMP, object, pp); |
| 1112 CompareImmediate(TMP, class_id, pp); | 1112 CompareImmediate(TMP, class_id, pp); |
| 1113 } | 1113 } |
| 1114 | 1114 |
| 1115 | 1115 |
| 1116 void Assembler::LoadTaggedClassIdMayBeSmi(Register result, Register object) { | 1116 void Assembler::LoadTaggedClassIdMayBeSmi(Register result, Register object) { |
| 1117 // Load up a null object. We only need it so we can use LoadClassId on it in | 1117 // Load up a null object. We only need it so we can use LoadClassId on it in |
| 1118 // the case that object is a Smi.. | 1118 // the case that object is a Smi.. |
| 1119 LoadObject(TMP, Object::null_object(), PP); | 1119 LoadObject(TMP, Object::null_object(), PP); |
| 1120 // Check if the object is a Smi. | 1120 // Check if the object is a Smi. |
| 1121 tsti(object, kSmiTagMask); | 1121 tsti(object, Immediate(kSmiTagMask)); |
| 1122 // If the object *is* a Smi, use the null object instead. o/w leave alone. | 1122 // If the object *is* a Smi, use the null object instead. o/w leave alone. |
| 1123 csel(TMP, TMP, object, EQ); | 1123 csel(TMP, TMP, object, EQ); |
| 1124 // Loads either the cid of the object if it isn't a Smi, or the cid of null | 1124 // Loads either the cid of the object if it isn't a Smi, or the cid of null |
| 1125 // if it is a Smi, which will be ignored. | 1125 // if it is a Smi, which will be ignored. |
| 1126 LoadClassId(result, TMP, PP); | 1126 LoadClassId(result, TMP, PP); |
| 1127 | 1127 |
| 1128 LoadImmediate(TMP, kSmiCid, PP); | 1128 LoadImmediate(TMP, kSmiCid, PP); |
| 1129 // If object is a Smi, move the Smi cid into result. o/w leave alone. | 1129 // If object is a Smi, move the Smi cid into result. o/w leave alone. |
| 1130 csel(result, TMP, result, EQ); | 1130 csel(result, TMP, result, EQ); |
| 1131 // Finally, tag the result. | 1131 // Finally, tag the result. |
| 1132 SmiTag(result); | 1132 SmiTag(result); |
| 1133 } | 1133 } |
| 1134 | 1134 |
| 1135 | 1135 |
| 1136 // Frame entry and exit. | 1136 // Frame entry and exit. |
| 1137 void Assembler::ReserveAlignedFrameSpace(intptr_t frame_space) { | 1137 void Assembler::ReserveAlignedFrameSpace(intptr_t frame_space) { |
| 1138 // Reserve space for arguments and align frame before entering | 1138 // Reserve space for arguments and align frame before entering |
| 1139 // the C++ world. | 1139 // the C++ world. |
| 1140 if (frame_space != 0) { | 1140 if (frame_space != 0) { |
| 1141 AddImmediate(SP, SP, -frame_space, kNoPP); | 1141 AddImmediate(SP, SP, -frame_space, kNoPP); |
| 1142 } | 1142 } |
| 1143 if (OS::ActivationFrameAlignment() > 1) { | 1143 if (OS::ActivationFrameAlignment() > 1) { |
| 1144 andi(SP, SP, ~(OS::ActivationFrameAlignment() - 1)); | 1144 andi(SP, SP, Immediate(~(OS::ActivationFrameAlignment() - 1))); |
| 1145 } | 1145 } |
| 1146 } | 1146 } |
| 1147 | 1147 |
| 1148 | 1148 |
| 1149 void Assembler::EnterFrame(intptr_t frame_size) { | 1149 void Assembler::EnterFrame(intptr_t frame_size) { |
| 1150 Push(LR); | 1150 Push(LR); |
| 1151 Push(FP); | 1151 Push(FP); |
| 1152 mov(FP, SP); | 1152 mov(FP, SP); |
| 1153 | 1153 |
| 1154 if (frame_size > 0) { | 1154 if (frame_size > 0) { |
| 1155 sub(SP, SP, Operand(frame_size)); | 1155 sub(SP, SP, Operand(frame_size)); |
| 1156 } | 1156 } |
| 1157 } | 1157 } |
| 1158 | 1158 |
| 1159 | 1159 |
| 1160 void Assembler::LeaveFrame() { | 1160 void Assembler::LeaveFrame() { |
| 1161 mov(SP, FP); | 1161 mov(SP, FP); |
| 1162 Pop(FP); | 1162 Pop(FP); |
| 1163 Pop(LR); | 1163 Pop(LR); |
| 1164 } | 1164 } |
| 1165 | 1165 |
| 1166 | 1166 |
| 1167 void Assembler::EnterDartFrame(intptr_t frame_size) { | 1167 void Assembler::EnterDartFrame(intptr_t frame_size) { |
| 1168 // Setup the frame. | 1168 // Setup the frame. |
| 1169 adr(TMP, -CodeSize()); // TMP gets PC marker. | 1169 adr(TMP, Immediate(-CodeSize())); // TMP gets PC marker. |
| 1170 EnterFrame(0); | 1170 EnterFrame(0); |
| 1171 Push(TMP); // Save PC Marker. | 1171 Push(TMP); // Save PC Marker. |
| 1172 TagAndPushPP(); // Save PP. | 1172 TagAndPushPP(); // Save PP. |
| 1173 | 1173 |
| 1174 // Load the pool pointer. | 1174 // Load the pool pointer. |
| 1175 LoadPoolPointer(PP); | 1175 LoadPoolPointer(PP); |
| 1176 | 1176 |
| 1177 // Reserve space. | 1177 // Reserve space. |
| 1178 if (frame_size > 0) { | 1178 if (frame_size > 0) { |
| 1179 AddImmediate(SP, SP, -frame_size, PP); | 1179 AddImmediate(SP, SP, -frame_size, PP); |
| 1180 } | 1180 } |
| 1181 } | 1181 } |
| 1182 | 1182 |
| 1183 | 1183 |
| 1184 void Assembler::EnterDartFrameWithInfo(intptr_t frame_size, Register new_pp) { | 1184 void Assembler::EnterDartFrameWithInfo(intptr_t frame_size, Register new_pp) { |
| 1185 // Setup the frame. | 1185 // Setup the frame. |
| 1186 adr(TMP, -CodeSize()); // TMP gets PC marker. | 1186 adr(TMP, Immediate(-CodeSize())); // TMP gets PC marker. |
| 1187 EnterFrame(0); | 1187 EnterFrame(0); |
| 1188 Push(TMP); // Save PC Marker. | 1188 Push(TMP); // Save PC Marker. |
| 1189 TagAndPushPP(); // Save PP. | 1189 TagAndPushPP(); // Save PP. |
| 1190 | 1190 |
| 1191 // Load the pool pointer. | 1191 // Load the pool pointer. |
| 1192 if (new_pp == kNoPP) { | 1192 if (new_pp == kNoPP) { |
| 1193 LoadPoolPointer(PP); | 1193 LoadPoolPointer(PP); |
| 1194 } else { | 1194 } else { |
| 1195 mov(PP, new_pp); | 1195 mov(PP, new_pp); |
| 1196 } | 1196 } |
| 1197 | 1197 |
| 1198 // Reserve space. | 1198 // Reserve space. |
| 1199 if (frame_size > 0) { | 1199 if (frame_size > 0) { |
| 1200 AddImmediate(SP, SP, -frame_size, PP); | 1200 AddImmediate(SP, SP, -frame_size, PP); |
| 1201 } | 1201 } |
| 1202 } | 1202 } |
| 1203 | 1203 |
| 1204 | 1204 |
| 1205 // On entry to a function compiled for OSR, the caller's frame pointer, the | 1205 // On entry to a function compiled for OSR, the caller's frame pointer, the |
| 1206 // stack locals, and any copied parameters are already in place. The frame | 1206 // stack locals, and any copied parameters are already in place. The frame |
| 1207 // pointer is already set up. The PC marker is not correct for the | 1207 // pointer is already set up. The PC marker is not correct for the |
| 1208 // optimized function and there may be extra space for spill slots to | 1208 // optimized function and there may be extra space for spill slots to |
| 1209 // allocate. We must also set up the pool pointer for the function. | 1209 // allocate. We must also set up the pool pointer for the function. |
| 1210 void Assembler::EnterOsrFrame(intptr_t extra_size, Register new_pp) { | 1210 void Assembler::EnterOsrFrame(intptr_t extra_size, Register new_pp) { |
| 1211 Comment("EnterOsrFrame"); | 1211 Comment("EnterOsrFrame"); |
| 1212 adr(TMP, -CodeSize()); | 1212 adr(TMP, Immediate(-CodeSize())); |
| 1213 | 1213 |
| 1214 StoreToOffset(TMP, FP, kPcMarkerSlotFromFp * kWordSize, kNoPP); | 1214 StoreToOffset(TMP, FP, kPcMarkerSlotFromFp * kWordSize, kNoPP); |
| 1215 | 1215 |
| 1216 // Setup pool pointer for this dart function. | 1216 // Setup pool pointer for this dart function. |
| 1217 if (new_pp == kNoPP) { | 1217 if (new_pp == kNoPP) { |
| 1218 LoadPoolPointer(PP); | 1218 LoadPoolPointer(PP); |
| 1219 } else { | 1219 } else { |
| 1220 mov(PP, new_pp); | 1220 mov(PP, new_pp); |
| 1221 } | 1221 } |
| 1222 | 1222 |
| (...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1517 add(base, array, Operand(index, LSL, shift)); | 1517 add(base, array, Operand(index, LSL, shift)); |
| 1518 } | 1518 } |
| 1519 const OperandSize size = Address::OperandSizeFor(cid); | 1519 const OperandSize size = Address::OperandSizeFor(cid); |
| 1520 ASSERT(Address::CanHoldOffset(offset, Address::Offset, size)); | 1520 ASSERT(Address::CanHoldOffset(offset, Address::Offset, size)); |
| 1521 return Address(base, offset, Address::Offset, size); | 1521 return Address(base, offset, Address::Offset, size); |
| 1522 } | 1522 } |
| 1523 | 1523 |
| 1524 } // namespace dart | 1524 } // namespace dart |
| 1525 | 1525 |
| 1526 #endif // defined TARGET_ARCH_ARM64 | 1526 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |