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