| 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 399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 410 imm &= ~kSmiTagMask; // Mask off the tag bits. | 410 imm &= ~kSmiTagMask; // Mask off the tag bits. |
| 411 const int32_t offset = Array::element_offset(FindImmediate(imm)); | 411 const int32_t offset = Array::element_offset(FindImmediate(imm)); |
| 412 LoadWordFromPoolOffset(reg, pp, offset); | 412 LoadWordFromPoolOffset(reg, pp, offset); |
| 413 if (val_smi_tag != 0) { | 413 if (val_smi_tag != 0) { |
| 414 // Add back the tag bits. | 414 // Add back the tag bits. |
| 415 orri(reg, reg, val_smi_tag); | 415 orri(reg, reg, val_smi_tag); |
| 416 } | 416 } |
| 417 } else { | 417 } else { |
| 418 // TODO(zra): Since this sequence only needs to be decodable, it can be | 418 // TODO(zra): Since this sequence only needs to be decodable, it can be |
| 419 // of variable length. | 419 // of variable length. |
| 420 LoadPatchableImmediate(reg, imm); | 420 LoadImmediateFixed(reg, imm); |
| 421 } | 421 } |
| 422 } | 422 } |
| 423 | 423 |
| 424 | 424 |
| 425 void Assembler::LoadPatchableImmediate(Register reg, int64_t imm) { | 425 void Assembler::LoadImmediateFixed(Register reg, int64_t imm) { |
| 426 const uint32_t w0 = Utils::Low32Bits(imm); | 426 const uint32_t w0 = Utils::Low32Bits(imm); |
| 427 const uint32_t w1 = Utils::High32Bits(imm); | 427 const uint32_t w1 = Utils::High32Bits(imm); |
| 428 const uint16_t h0 = Utils::Low16Bits(w0); | 428 const uint16_t h0 = Utils::Low16Bits(w0); |
| 429 const uint16_t h1 = Utils::High16Bits(w0); | 429 const uint16_t h1 = Utils::High16Bits(w0); |
| 430 const uint16_t h2 = Utils::Low16Bits(w1); | 430 const uint16_t h2 = Utils::Low16Bits(w1); |
| 431 const uint16_t h3 = Utils::High16Bits(w1); | 431 const uint16_t h3 = Utils::High16Bits(w1); |
| 432 movz(reg, h0, 0); | 432 movz(reg, h0, 0); |
| 433 movk(reg, h1, 1); | 433 movk(reg, h1, 1); |
| 434 movk(reg, h2, 2); | 434 movk(reg, h2, 2); |
| 435 movk(reg, h3, 3); | 435 movk(reg, h3, 3); |
| 436 } | 436 } |
| 437 | 437 |
| 438 | 438 |
| 439 void Assembler::LoadImmediate(Register reg, int64_t imm, Register pp) { | 439 void Assembler::LoadImmediate(Register reg, int64_t imm, Register pp) { |
| 440 Comment("LoadImmediate"); | 440 Comment("LoadImmediate"); |
| 441 if (CanLoadImmediateFromPool(imm, pp)) { | 441 if (CanLoadImmediateFromPool(imm, pp)) { |
| 442 // It's a 64-bit constant and we're not in the VM isolate, so load from | 442 // It's a 64-bit constant and we're not in the VM isolate, so load from |
| 443 // object pool. | 443 // object pool. |
| 444 // Save the bits that must be masked-off for the SmiTag | 444 // Save the bits that must be masked-off for the SmiTag |
| 445 int64_t val_smi_tag = imm & kSmiTagMask; | 445 int64_t val_smi_tag = imm & kSmiTagMask; |
| 446 imm &= ~kSmiTagMask; // Mask off the tag bits. | 446 imm &= ~kSmiTagMask; // Mask off the tag bits. |
| 447 const int32_t offset = Array::element_offset(FindImmediate(imm)); | 447 const int32_t offset = Array::element_offset(FindImmediate(imm)); |
| 448 LoadWordFromPoolOffset(reg, pp, offset); | 448 LoadWordFromPoolOffset(reg, pp, offset); |
| 449 if (val_smi_tag != 0) { | 449 if (val_smi_tag != 0) { |
| 450 // Add back the tag bits. | 450 // Add back the tag bits. |
| 451 orri(reg, reg, val_smi_tag); | 451 orri(reg, reg, val_smi_tag); |
| 452 } | 452 } |
| 453 } else { | 453 } else { |
| 454 // 0. Is it 0? |
| 455 if (imm == 0) { |
| 456 movz(reg, 0, 0); |
| 457 return; |
| 458 } |
| 459 |
| 454 // 1. Can we use one orri operation? | 460 // 1. Can we use one orri operation? |
| 455 Operand op; | 461 Operand op; |
| 456 Operand::OperandType ot; | 462 Operand::OperandType ot; |
| 457 ot = Operand::CanHold(imm, kXRegSizeInBits, &op); | 463 ot = Operand::CanHold(imm, kXRegSizeInBits, &op); |
| 458 if (ot == Operand::BitfieldImm) { | 464 if (ot == Operand::BitfieldImm) { |
| 459 orri(reg, ZR, imm); | 465 orri(reg, ZR, imm); |
| 460 return; | 466 return; |
| 461 } | 467 } |
| 462 | 468 |
| 463 // 2. Fall back on movz, movk, movn. | 469 // 2. Fall back on movz, movk, movn. |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 712 // Load the pool pointer. | 718 // Load the pool pointer. |
| 713 LoadPoolPointer(PP); | 719 LoadPoolPointer(PP); |
| 714 | 720 |
| 715 // Reserve space. | 721 // Reserve space. |
| 716 if (frame_size > 0) { | 722 if (frame_size > 0) { |
| 717 sub(SP, SP, Operand(frame_size)); | 723 sub(SP, SP, Operand(frame_size)); |
| 718 } | 724 } |
| 719 } | 725 } |
| 720 | 726 |
| 721 | 727 |
| 728 void Assembler::EnterDartFrameWithInfo(intptr_t frame_size, Register new_pp) { |
| 729 // Setup the frame. |
| 730 adr(TMP, 0); // TMP gets PC of this instruction. |
| 731 EnterFrame(0); |
| 732 Push(TMP); // Save PC Marker. |
| 733 PushPP(); // Save PP. |
| 734 |
| 735 // Load the pool pointer. |
| 736 if (new_pp == kNoRegister) { |
| 737 LoadPoolPointer(PP); |
| 738 } else { |
| 739 mov(PP, new_pp); |
| 740 } |
| 741 |
| 742 // Reserve space. |
| 743 if (frame_size > 0) { |
| 744 sub(SP, SP, Operand(frame_size)); |
| 745 } |
| 746 } |
| 747 |
| 748 |
| 749 // On entry to a function compiled for OSR, the caller's frame pointer, the |
| 750 // stack locals, and any copied parameters are already in place. The frame |
| 751 // pointer is already set up. The PC marker is not correct for the |
| 752 // optimized function and there may be extra space for spill slots to |
| 753 // allocate. We must also set up the pool pointer for the function. |
| 754 void Assembler::EnterOsrFrame(intptr_t extra_size, Register new_pp) { |
| 755 const intptr_t offset = CodeSize(); |
| 756 |
| 757 Comment("EnterOsrFrame"); |
| 758 adr(TMP, 0); |
| 759 |
| 760 AddImmediate(TMP, TMP, -offset, kNoRegister); |
| 761 StoreToOffset(TMP, FP, kPcMarkerSlotFromFp * kWordSize); |
| 762 |
| 763 // Setup pool pointer for this dart function. |
| 764 if (new_pp == kNoRegister) { |
| 765 LoadPoolPointer(PP); |
| 766 } else { |
| 767 mov(PP, new_pp); |
| 768 } |
| 769 |
| 770 if (extra_size > 0) { |
| 771 sub(SP, SP, Operand(extra_size)); |
| 772 } |
| 773 } |
| 774 |
| 775 |
| 722 void Assembler::LeaveDartFrame() { | 776 void Assembler::LeaveDartFrame() { |
| 723 // Restore and untag PP. | 777 // Restore and untag PP. |
| 724 LoadFromOffset(PP, FP, kSavedCallerPpSlotFromFp * kWordSize); | 778 LoadFromOffset(PP, FP, kSavedCallerPpSlotFromFp * kWordSize); |
| 725 sub(PP, PP, Operand(kHeapObjectTag)); | 779 sub(PP, PP, Operand(kHeapObjectTag)); |
| 726 LeaveFrame(); | 780 LeaveFrame(); |
| 727 } | 781 } |
| 728 | 782 |
| 729 | 783 |
| 730 void Assembler::EnterCallRuntimeFrame(intptr_t frame_size) { | 784 void Assembler::EnterCallRuntimeFrame(intptr_t frame_size) { |
| 731 EnterFrame(0); | 785 EnterFrame(0); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 760 | 814 |
| 761 | 815 |
| 762 void Assembler::CallRuntime(const RuntimeEntry& entry, | 816 void Assembler::CallRuntime(const RuntimeEntry& entry, |
| 763 intptr_t argument_count) { | 817 intptr_t argument_count) { |
| 764 entry.Call(this, argument_count); | 818 entry.Call(this, argument_count); |
| 765 } | 819 } |
| 766 | 820 |
| 767 } // namespace dart | 821 } // namespace dart |
| 768 | 822 |
| 769 #endif // defined TARGET_ARCH_ARM64 | 823 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |