Chromium Code Reviews| 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 #ifndef VM_ASSEMBLER_ARM64_H_ | 5 #ifndef VM_ASSEMBLER_ARM64_H_ |
| 6 #define VM_ASSEMBLER_ARM64_H_ | 6 #define VM_ASSEMBLER_ARM64_H_ |
| 7 | 7 |
| 8 #ifndef VM_ASSEMBLER_H_ | 8 #ifndef VM_ASSEMBLER_H_ |
| 9 #error Do not include assembler_arm64.h directly; use assembler.h instead. | 9 #error Do not include assembler_arm64.h directly; use assembler.h instead. |
| 10 #endif | 10 #endif |
| (...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 371 static void InitializeMemoryWithBreakpoints(uword data, intptr_t length); | 371 static void InitializeMemoryWithBreakpoints(uword data, intptr_t length); |
| 372 | 372 |
| 373 void Comment(const char* format, ...) PRINTF_ATTRIBUTE(2, 3); | 373 void Comment(const char* format, ...) PRINTF_ATTRIBUTE(2, 3); |
| 374 | 374 |
| 375 const Code::Comments& GetCodeComments() const; | 375 const Code::Comments& GetCodeComments() const; |
| 376 | 376 |
| 377 static const char* RegisterName(Register reg); | 377 static const char* RegisterName(Register reg); |
| 378 | 378 |
| 379 static const char* FpuRegisterName(FpuRegister reg); | 379 static const char* FpuRegisterName(FpuRegister reg); |
| 380 | 380 |
| 381 void SetPrologueOffset() { | |
| 382 if (prologue_offset_ == -1) { | |
| 383 prologue_offset_ = CodeSize(); | |
| 384 } | |
| 385 } | |
| 386 | |
| 387 void ReserveAlignedFrameSpace(intptr_t frame_space); | |
| 388 | |
| 381 // TODO(zra): Make sure this is right. | 389 // TODO(zra): Make sure this is right. |
| 382 // Instruction pattern from entrypoint is used in Dart frame prologs | 390 // Instruction pattern from entrypoint is used in Dart frame prologs |
| 383 // to set up the frame and save a PC which can be used to figure out the | 391 // to set up the frame and save a PC which can be used to figure out the |
| 384 // RawInstruction object corresponding to the code running in the frame. | 392 // RawInstruction object corresponding to the code running in the frame. |
| 385 static const intptr_t kEntryPointToPcMarkerOffset = 0; | 393 static const intptr_t kEntryPointToPcMarkerOffset = 0; |
| 386 | 394 |
| 387 // Emit data (e.g encoded instruction or immediate) in instruction stream. | 395 // Emit data (e.g encoded instruction or immediate) in instruction stream. |
| 388 void Emit(int32_t value); | 396 void Emit(int32_t value); |
| 389 | 397 |
| 390 // On some other platforms, we draw a distinction between safe and unsafe | 398 // On some other platforms, we draw a distinction between safe and unsafe |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 594 ldr(PP, Address(SP, 1 * kWordSize, Address::PostIndex)); | 602 ldr(PP, Address(SP, 1 * kWordSize, Address::PostIndex)); |
| 595 sub(PP, PP, Operand(kHeapObjectTag)); | 603 sub(PP, PP, Operand(kHeapObjectTag)); |
| 596 } | 604 } |
| 597 void tst(Register rn, Operand o) { | 605 void tst(Register rn, Operand o) { |
| 598 ands(ZR, rn, o); | 606 ands(ZR, rn, o); |
| 599 } | 607 } |
| 600 void tsti(Register rn, uint64_t imm) { | 608 void tsti(Register rn, uint64_t imm) { |
| 601 andis(ZR, rn, imm); | 609 andis(ZR, rn, imm); |
| 602 } | 610 } |
| 603 | 611 |
| 612 void SmiUntag(Register reg) { | |
| 613 add(reg, ZR, Operand(reg, ASR, kSmiTagSize)); | |
| 614 } | |
| 615 | |
| 604 // Branching to ExternalLabels. | 616 // Branching to ExternalLabels. |
| 605 void Branch(const ExternalLabel* label) { | 617 void Branch(const ExternalLabel* label) { |
| 606 LoadExternalLabel(TMP, label, kPatchable, PP); | 618 LoadExternalLabel(TMP, label, kPatchable, PP); |
| 607 br(TMP); | 619 br(TMP); |
| 608 } | 620 } |
| 609 | 621 |
| 610 void BranchPatchable(const ExternalLabel* label) { | 622 void BranchPatchable(const ExternalLabel* label) { |
| 611 LoadPatchableImmediate(TMP, label->address()); | 623 LoadPatchableImmediate(TMP, label->address()); |
| 612 br(TMP); | 624 br(TMP); |
| 613 } | 625 } |
| 614 | 626 |
| 615 void BranchLink(const ExternalLabel* label, Register pp) { | 627 void BranchLink(const ExternalLabel* label, Register pp) { |
| 616 if (Isolate::Current() == Dart::vm_isolate()) { | 628 if (Isolate::Current() == Dart::vm_isolate()) { |
| 617 LoadImmediate(TMP, label->address(), kNoRegister); | 629 LoadImmediate(TMP, label->address(), kNoRegister); |
| 618 blr(TMP); | 630 blr(TMP); |
| 619 } else { | 631 } else { |
| 620 LoadExternalLabel(TMP, label, kNotPatchable, pp); | 632 LoadExternalLabel(TMP, label, kNotPatchable, pp); |
| 621 blr(TMP); | 633 blr(TMP); |
| 622 } | 634 } |
| 623 } | 635 } |
| 624 | 636 |
| 625 void BranchLinkPatchable(const ExternalLabel* label) { | 637 void BranchLinkPatchable(const ExternalLabel* label) { |
| 626 LoadExternalLabel(TMP, label, kPatchable, PP); | 638 LoadExternalLabel(TMP, label, kPatchable, PP); |
| 627 blr(TMP); | 639 blr(TMP); |
| 628 } | 640 } |
| 629 | 641 |
| 642 void AddImmediate(Register dest, Register rn, int64_t imm, Register pp); | |
|
regis
2014/04/18 22:15:30
You should explain in a comment what is the purpos
zra
2014/04/18 23:24:21
Done.
| |
| 643 void CompareImmediate(Register rn, int64_t imm, Register pp); | |
| 644 void LoadFromOffset(Register dest, Register base, int32_t offset); | |
| 645 void LoadFieldFromOffset(Register dest, Register base, int32_t offset) { | |
| 646 LoadFromOffset(dest, base, offset - kHeapObjectTag); | |
| 647 } | |
| 648 void StoreToOffset(Register dest, Register base, int32_t offset); | |
| 649 void StoreFieldToOffset(Register dest, Register base, int32_t offset) { | |
| 650 StoreToOffset(dest, base, offset - kHeapObjectTag); | |
| 651 } | |
| 652 | |
| 630 // Object pool, loading from pool, etc. | 653 // Object pool, loading from pool, etc. |
| 631 void LoadPoolPointer(Register pp) { | 654 void LoadPoolPointer(Register pp); |
| 632 const intptr_t object_pool_pc_dist = | |
| 633 Instructions::HeaderSize() - Instructions::object_pool_offset() + | |
| 634 CodeSize(); | |
| 635 // PP <- Read(PC - object_pool_pc_dist). | |
| 636 ldr(pp, Address::PC(-object_pool_pc_dist)); | |
| 637 | |
| 638 // When in the PP register, the pool pointer is untagged. When we | |
| 639 // push it on the stack with PushPP it is tagged again. PopPP then untags | |
| 640 // when restoring from the stack. This will make loading from the object | |
| 641 // pool only one instruction for the first 4096 entries. Otherwise, because | |
| 642 // the offset wouldn't be aligned, it would always be at least two | |
| 643 // instructions. | |
| 644 sub(pp, pp, Operand(kHeapObjectTag)); | |
| 645 } | |
| 646 | 655 |
| 647 enum Patchability { | 656 enum Patchability { |
| 648 kPatchable, | 657 kPatchable, |
| 649 kNotPatchable, | 658 kNotPatchable, |
| 650 }; | 659 }; |
| 651 | 660 |
| 652 void LoadWordFromPoolOffset(Register dst, Register pp, uint32_t offset); | 661 void LoadWordFromPoolOffset(Register dst, Register pp, uint32_t offset); |
| 653 intptr_t FindExternalLabel(const ExternalLabel* label, | 662 intptr_t FindExternalLabel(const ExternalLabel* label, |
| 654 Patchability patchable); | 663 Patchability patchable); |
| 655 intptr_t FindObject(const Object& obj, Patchability patchable); | 664 intptr_t FindObject(const Object& obj, Patchability patchable); |
| 656 intptr_t FindImmediate(int64_t imm); | 665 intptr_t FindImmediate(int64_t imm); |
| 657 bool CanLoadObjectFromPool(const Object& object); | 666 bool CanLoadObjectFromPool(const Object& object); |
| 658 bool CanLoadImmediateFromPool(int64_t imm, Register pp); | 667 bool CanLoadImmediateFromPool(int64_t imm, Register pp); |
| 659 void LoadExternalLabel(Register dst, const ExternalLabel* label, | 668 void LoadExternalLabel(Register dst, const ExternalLabel* label, |
| 660 Patchability patchable, Register pp); | 669 Patchability patchable, Register pp); |
| 661 void LoadObject(Register dst, const Object& obj, Register pp); | 670 void LoadObject(Register dst, const Object& obj, Register pp); |
| 662 void LoadDecodableImmediate(Register reg, int64_t imm, Register pp); | 671 void LoadDecodableImmediate(Register reg, int64_t imm, Register pp); |
| 663 void LoadPatchableImmediate(Register reg, int64_t imm); | 672 void LoadPatchableImmediate(Register reg, int64_t imm); |
| 664 void LoadImmediate(Register reg, int64_t imm, Register pp); | 673 void LoadImmediate(Register reg, int64_t imm, Register pp); |
| 665 | 674 |
| 675 void PushObject(const Object& object, Register pp) { | |
| 676 LoadObject(TMP, object, pp); | |
| 677 Push(TMP); | |
| 678 } | |
| 679 | |
| 680 void EnterDartFrame(intptr_t frame_size); | |
| 681 void LeaveDartFrame(); | |
| 682 | |
| 683 void CallRuntime(const RuntimeEntry& entry, intptr_t argument_count); | |
| 684 | |
| 666 private: | 685 private: |
| 667 AssemblerBuffer buffer_; // Contains position independent code. | 686 AssemblerBuffer buffer_; // Contains position independent code. |
| 668 | 687 |
| 669 // Objects and patchable jump targets. | 688 // Objects and patchable jump targets. |
| 670 GrowableObjectArray& object_pool_; | 689 GrowableObjectArray& object_pool_; |
| 671 | 690 |
| 672 // Patchability of pool entries. | 691 // Patchability of pool entries. |
| 673 GrowableArray<Patchability> patchable_pool_entries_; | 692 GrowableArray<Patchability> patchable_pool_entries_; |
| 674 | 693 |
| 675 // Pair type parameter for DirectChainedHashMap. | 694 // Pair type parameter for DirectChainedHashMap. |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 823 | 842 |
| 824 int64_t DecodeImm19BranchOffset(int32_t instr) { | 843 int64_t DecodeImm19BranchOffset(int32_t instr) { |
| 825 const int32_t off = (((instr >> kImm19Shift) & kImm19Shift) << 13) >> 13; | 844 const int32_t off = (((instr >> kImm19Shift) & kImm19Shift) << 13) >> 13; |
| 826 return static_cast<int64_t>(off); | 845 return static_cast<int64_t>(off); |
| 827 } | 846 } |
| 828 | 847 |
| 829 void EmitCompareAndBranch(CompareAndBranchOp op, Register rt, int64_t imm, | 848 void EmitCompareAndBranch(CompareAndBranchOp op, Register rt, int64_t imm, |
| 830 OperandSize sz) { | 849 OperandSize sz) { |
| 831 ASSERT((sz == kDoubleWord) || (sz == kWord)); | 850 ASSERT((sz == kDoubleWord) || (sz == kWord)); |
| 832 ASSERT(Utils::IsInt(21, imm) && ((imm & 0x3) == 0)); | 851 ASSERT(Utils::IsInt(21, imm) && ((imm & 0x3) == 0)); |
| 852 ASSERT((rt != SP) && (rt != R31)); | |
| 853 const Register crt = ConcreteRegister(rt); | |
| 833 const int32_t size = (sz == kDoubleWord) ? B31 : 0; | 854 const int32_t size = (sz == kDoubleWord) ? B31 : 0; |
| 834 const int32_t encoded_offset = EncodeImm19BranchOffset(imm, 0); | 855 const int32_t encoded_offset = EncodeImm19BranchOffset(imm, 0); |
| 835 const int32_t encoding = | 856 const int32_t encoding = |
| 836 op | size | | 857 op | size | |
| 837 (static_cast<int32_t>(rt) << kRtShift) | | 858 (static_cast<int32_t>(crt) << kRtShift) | |
| 838 encoded_offset; | 859 encoded_offset; |
| 839 Emit(encoding); | 860 Emit(encoding); |
| 840 } | 861 } |
| 841 | 862 |
| 842 void EmitConditionalBranch(ConditionalBranchOp op, Condition cond, | 863 void EmitConditionalBranch(ConditionalBranchOp op, Condition cond, |
| 843 int64_t imm) { | 864 int64_t imm) { |
| 844 ASSERT(Utils::IsInt(21, imm) && ((imm & 0x3) == 0)); | 865 ASSERT(Utils::IsInt(21, imm) && ((imm & 0x3) == 0)); |
| 845 const int32_t encoding = | 866 const int32_t encoding = |
| 846 op | | 867 op | |
| 847 (static_cast<int32_t>(cond) << kCondShift) | | 868 (static_cast<int32_t>(cond) << kCondShift) | |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 862 EmitConditionalBranch(op, cond, dest); | 883 EmitConditionalBranch(op, cond, dest); |
| 863 } else { | 884 } else { |
| 864 const int64_t position = buffer_.Size(); | 885 const int64_t position = buffer_.Size(); |
| 865 ASSERT(CanEncodeImm19BranchOffset(position)); | 886 ASSERT(CanEncodeImm19BranchOffset(position)); |
| 866 EmitConditionalBranch(op, cond, label->position_); | 887 EmitConditionalBranch(op, cond, label->position_); |
| 867 label->LinkTo(position); | 888 label->LinkTo(position); |
| 868 } | 889 } |
| 869 } | 890 } |
| 870 | 891 |
| 871 void EmitUnconditionalBranchRegOp(UnconditionalBranchRegOp op, Register rn) { | 892 void EmitUnconditionalBranchRegOp(UnconditionalBranchRegOp op, Register rn) { |
| 893 ASSERT((rn != SP) && (rn != R31)); | |
| 894 const Register crn = ConcreteRegister(rn); | |
| 872 const int32_t encoding = | 895 const int32_t encoding = |
| 873 op | (static_cast<int32_t>(rn) << kRnShift); | 896 op | (static_cast<int32_t>(crn) << kRnShift); |
| 874 Emit(encoding); | 897 Emit(encoding); |
| 875 } | 898 } |
| 876 | 899 |
| 877 void EmitExceptionGenOp(ExceptionGenOp op, uint16_t imm) { | 900 void EmitExceptionGenOp(ExceptionGenOp op, uint16_t imm) { |
| 878 const int32_t encoding = | 901 const int32_t encoding = |
| 879 op | (static_cast<int32_t>(imm) << kImm16Shift); | 902 op | (static_cast<int32_t>(imm) << kImm16Shift); |
| 880 Emit(encoding); | 903 Emit(encoding); |
| 881 } | 904 } |
| 882 | 905 |
| 883 void EmitMoveWideOp(MoveWideOp op, Register rd, uint16_t imm, int hw_idx, | 906 void EmitMoveWideOp(MoveWideOp op, Register rd, uint16_t imm, int hw_idx, |
| 884 OperandSize sz) { | 907 OperandSize sz) { |
| 885 ASSERT((hw_idx >= 0) && (hw_idx <= 3)); | 908 ASSERT((hw_idx >= 0) && (hw_idx <= 3)); |
| 886 ASSERT((sz == kDoubleWord) || (sz == kWord)); | 909 ASSERT((sz == kDoubleWord) || (sz == kWord)); |
| 887 const int32_t size = (sz == kDoubleWord) ? B31 : 0; | 910 const int32_t size = (sz == kDoubleWord) ? B31 : 0; |
| 888 const int32_t encoding = | 911 const int32_t encoding = |
| 889 op | size | | 912 op | size | |
| 890 (static_cast<int32_t>(rd) << kRdShift) | | 913 (static_cast<int32_t>(rd) << kRdShift) | |
| 891 (static_cast<int32_t>(hw_idx) << kHWShift) | | 914 (static_cast<int32_t>(hw_idx) << kHWShift) | |
| 892 (static_cast<int32_t>(imm) << kImm16Shift); | 915 (static_cast<int32_t>(imm) << kImm16Shift); |
| 893 Emit(encoding); | 916 Emit(encoding); |
| 894 } | 917 } |
| 895 | 918 |
| 896 void EmitLoadStoreReg(LoadStoreRegOp op, Register rt, Address a, | 919 void EmitLoadStoreReg(LoadStoreRegOp op, Register rt, Address a, |
| 897 OperandSize sz) { | 920 OperandSize sz) { |
| 921 const Register crt = ConcreteRegister(rt); | |
| 898 const int32_t size = Log2OperandSizeBytes(sz); | 922 const int32_t size = Log2OperandSizeBytes(sz); |
| 899 const int32_t encoding = | 923 const int32_t encoding = |
| 900 op | (size << kSzShift) | | 924 op | (size << kSzShift) | |
| 901 (static_cast<int32_t>(rt) << kRtShift) | | 925 (static_cast<int32_t>(crt) << kRtShift) | |
| 902 a.encoding(); | 926 a.encoding(); |
| 903 Emit(encoding); | 927 Emit(encoding); |
| 904 } | 928 } |
| 905 | 929 |
| 906 void EmitLoadRegLiteral(LoadRegLiteralOp op, Register rt, Address a, | 930 void EmitLoadRegLiteral(LoadRegLiteralOp op, Register rt, Address a, |
| 907 OperandSize sz) { | 931 OperandSize sz) { |
| 908 ASSERT((sz == kDoubleWord) || (sz == kWord)); | 932 ASSERT((sz == kDoubleWord) || (sz == kWord)); |
| 933 ASSERT((rt != SP) && (rt != R31)); | |
| 934 const Register crt = ConcreteRegister(rt); | |
| 909 const int32_t size = (sz == kDoubleWord) ? B30 : 0; | 935 const int32_t size = (sz == kDoubleWord) ? B30 : 0; |
| 910 const int32_t encoding = | 936 const int32_t encoding = |
| 911 op | size | | 937 op | size | |
| 912 (static_cast<int32_t>(rt) << kRtShift) | | 938 (static_cast<int32_t>(crt) << kRtShift) | |
| 913 a.encoding(); | 939 a.encoding(); |
| 914 Emit(encoding); | 940 Emit(encoding); |
| 915 } | 941 } |
| 916 | 942 |
| 917 void EmitPCRelOp(PCRelOp op, Register rd, int64_t imm) { | 943 void EmitPCRelOp(PCRelOp op, Register rd, int64_t imm) { |
| 918 ASSERT(Utils::IsInt(21, imm)); | 944 ASSERT(Utils::IsInt(21, imm)); |
| 919 ASSERT((rd != R31) && (rd != SP)); | 945 ASSERT((rd != R31) && (rd != SP)); |
| 920 const Register crd = ConcreteRegister(rd); | 946 const Register crd = ConcreteRegister(rd); |
| 921 const int32_t loimm = (imm & 0x3) << 29; | 947 const int32_t loimm = (imm & 0x3) << 29; |
| 922 const int32_t hiimm = ((imm >> 2) << kImm19Shift) & kImm19Mask; | 948 const int32_t hiimm = ((imm >> 2) << kImm19Shift) & kImm19Mask; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 960 Emit(encoding); | 986 Emit(encoding); |
| 961 } | 987 } |
| 962 | 988 |
| 963 DISALLOW_ALLOCATION(); | 989 DISALLOW_ALLOCATION(); |
| 964 DISALLOW_COPY_AND_ASSIGN(Assembler); | 990 DISALLOW_COPY_AND_ASSIGN(Assembler); |
| 965 }; | 991 }; |
| 966 | 992 |
| 967 } // namespace dart | 993 } // namespace dart |
| 968 | 994 |
| 969 #endif // VM_ASSEMBLER_ARM64_H_ | 995 #endif // VM_ASSEMBLER_ARM64_H_ |
| OLD | NEW |