OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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_ARM_H_ | 5 #ifndef VM_ASSEMBLER_ARM_H_ |
6 #define VM_ASSEMBLER_ARM_H_ | 6 #define VM_ASSEMBLER_ARM_H_ |
7 | 7 |
8 #ifndef VM_ASSEMBLER_H_ | 8 #ifndef VM_ASSEMBLER_H_ |
9 #error Do not include assembler_arm.h directly; use assembler.h instead. | 9 #error Do not include assembler_arm.h directly; use assembler.h instead. |
10 #endif | 10 #endif |
(...skipping 588 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
599 // The words of qd and qm are interleaved with the low words of the result | 599 // The words of qd and qm are interleaved with the low words of the result |
600 // in qd and the high words in qm. | 600 // in qd and the high words in qm. |
601 void vzipqw(QRegister qd, QRegister qm); | 601 void vzipqw(QRegister qd, QRegister qm); |
602 | 602 |
603 // Branch instructions. | 603 // Branch instructions. |
604 void b(Label* label, Condition cond = AL); | 604 void b(Label* label, Condition cond = AL); |
605 void bl(Label* label, Condition cond = AL); | 605 void bl(Label* label, Condition cond = AL); |
606 void bx(Register rm, Condition cond = AL); | 606 void bx(Register rm, Condition cond = AL); |
607 void blx(Register rm, Condition cond = AL); | 607 void blx(Register rm, Condition cond = AL); |
608 | 608 |
609 // Macros. | 609 void Branch(const StubEntry& stub_entry, |
610 // Branch to an entry address. Call sequence is never patched. | 610 Patchability patchable = kNotPatchable, |
611 void Branch(const StubEntry& stub_entry, Condition cond = AL); | 611 Register pp = PP, |
612 | 612 Condition cond = AL); |
613 // Branch to an entry address. Call sequence can be patched or even replaced. | |
614 void BranchPatchable(const StubEntry& stub_entry); | |
615 | 613 |
616 void BranchLink(const StubEntry& stub_entry, | 614 void BranchLink(const StubEntry& stub_entry, |
617 Patchability patchable = kNotPatchable); | 615 Patchability patchable = kNotPatchable); |
618 void BranchLink(const ExternalLabel* label, Patchability patchable); | 616 void BranchLink(const Code& code, Patchability patchable); |
619 | 617 |
620 // Branch and link to an entry address. Call sequence can be patched. | 618 // Branch and link to an entry address. Call sequence can be patched. |
621 void BranchLinkPatchable(const StubEntry& stub_entry); | 619 void BranchLinkPatchable(const StubEntry& stub_entry); |
| 620 void BranchLinkPatchable(const Code& code); |
622 | 621 |
623 // Branch and link to [base + offset]. Call sequence is never patched. | 622 // Branch and link to [base + offset]. Call sequence is never patched. |
624 void BranchLinkOffset(Register base, int32_t offset); | 623 void BranchLinkOffset(Register base, int32_t offset); |
625 | 624 |
626 // Add signed immediate value to rd. May clobber IP. | 625 // Add signed immediate value to rd. May clobber IP. |
627 void AddImmediate(Register rd, int32_t value, Condition cond = AL); | 626 void AddImmediate(Register rd, int32_t value, Condition cond = AL); |
628 void AddImmediate(Register rd, Register rn, int32_t value, | 627 void AddImmediate(Register rd, Register rn, int32_t value, |
629 Condition cond = AL); | 628 Condition cond = AL); |
630 void AddImmediateSetFlags(Register rd, Register rn, int32_t value, | 629 void AddImmediateSetFlags(Register rd, Register rn, int32_t value, |
631 Condition cond = AL); | 630 Condition cond = AL); |
(...skipping 22 matching lines...) Expand all Loading... |
654 void LoadImmediate(Register rd, int32_t value, Condition cond = AL); | 653 void LoadImmediate(Register rd, int32_t value, Condition cond = AL); |
655 // These two may clobber IP. | 654 // These two may clobber IP. |
656 void LoadSImmediate(SRegister sd, float value, Condition cond = AL); | 655 void LoadSImmediate(SRegister sd, float value, Condition cond = AL); |
657 void LoadDImmediate(DRegister dd, double value, | 656 void LoadDImmediate(DRegister dd, double value, |
658 Register scratch, Condition cond = AL); | 657 Register scratch, Condition cond = AL); |
659 | 658 |
660 void MarkExceptionHandler(Label* label); | 659 void MarkExceptionHandler(Label* label); |
661 | 660 |
662 void Drop(intptr_t stack_elements); | 661 void Drop(intptr_t stack_elements); |
663 | 662 |
664 void LoadPoolPointer(); | 663 void RestoreCodePointer(); |
| 664 void LoadPoolPointer(Register reg = PP); |
665 | 665 |
666 void LoadIsolate(Register rd); | 666 void LoadIsolate(Register rd); |
667 | 667 |
668 void LoadObject(Register rd, const Object& object, Condition cond = AL); | 668 void LoadObject(Register rd, const Object& object, Condition cond = AL); |
669 void LoadUniqueObject(Register rd, const Object& object, Condition cond = AL); | 669 void LoadUniqueObject(Register rd, const Object& object, Condition cond = AL); |
670 void LoadExternalLabel(Register dst, | 670 void LoadExternalLabel(Register dst, |
671 const ExternalLabel* label, | 671 const ExternalLabel* label, |
672 Patchability patchable, | 672 Patchability patchable, |
673 Condition cond = AL); | 673 Condition cond = AL); |
| 674 void LoadFunctionFromCalleePool(Register dst, |
| 675 const Function& function, |
| 676 Register new_pp); |
674 void PushObject(const Object& object); | 677 void PushObject(const Object& object); |
675 void CompareObject(Register rn, const Object& object); | 678 void CompareObject(Register rn, const Object& object); |
676 | 679 |
677 // When storing into a heap object field, knowledge of the previous content | 680 // When storing into a heap object field, knowledge of the previous content |
678 // is expressed through these constants. | 681 // is expressed through these constants. |
679 enum FieldContent { | 682 enum FieldContent { |
680 kEmptyOrSmiOrNull, // Empty = garbage/zapped in release/debug mode. | 683 kEmptyOrSmiOrNull, // Empty = garbage/zapped in release/debug mode. |
681 kHeapObjectOrSmi, | 684 kHeapObjectOrSmi, |
682 kOnlySmi, | 685 kOnlySmi, |
683 }; | 686 }; |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
749 Label* miss); | 752 Label* miss); |
750 | 753 |
751 void UpdateRangeFeedback(Register value, | 754 void UpdateRangeFeedback(Register value, |
752 intptr_t idx, | 755 intptr_t idx, |
753 Register ic_data, | 756 Register ic_data, |
754 Register scratch1, | 757 Register scratch1, |
755 Register scratch2, | 758 Register scratch2, |
756 Label* miss); | 759 Label* miss); |
757 | 760 |
758 intptr_t FindImmediate(int32_t imm); | 761 intptr_t FindImmediate(int32_t imm); |
759 void LoadWordFromPoolOffset(Register rd, int32_t offset, Condition cond = AL); | |
760 void LoadFromOffset(OperandSize type, | 762 void LoadFromOffset(OperandSize type, |
761 Register reg, | 763 Register reg, |
762 Register base, | 764 Register base, |
763 int32_t offset, | 765 int32_t offset, |
764 Condition cond = AL); | 766 Condition cond = AL); |
765 void LoadFieldFromOffset(OperandSize type, | 767 void LoadFieldFromOffset(OperandSize type, |
766 Register reg, | 768 Register reg, |
767 Register base, | 769 Register base, |
768 int32_t offset, | 770 int32_t offset, |
769 Condition cond = AL) { | 771 Condition cond = AL) { |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
861 // Untag the value in the register assuming it is a smi. | 863 // Untag the value in the register assuming it is a smi. |
862 // Untagging shifts tag bit into the carry flag - if carry is clear | 864 // Untagging shifts tag bit into the carry flag - if carry is clear |
863 // assumption was correct. In this case jump to the is_smi label. | 865 // assumption was correct. In this case jump to the is_smi label. |
864 // Otherwise fall-through. | 866 // Otherwise fall-through. |
865 void SmiUntag(Register dst, Register src, Label* is_smi) { | 867 void SmiUntag(Register dst, Register src, Label* is_smi) { |
866 ASSERT(kSmiTagSize == 1); | 868 ASSERT(kSmiTagSize == 1); |
867 Asrs(dst, src, Operand(kSmiTagSize)); | 869 Asrs(dst, src, Operand(kSmiTagSize)); |
868 b(is_smi, CC); | 870 b(is_smi, CC); |
869 } | 871 } |
870 | 872 |
| 873 void CheckCodePointer(); |
| 874 |
871 // Function frame setup and tear down. | 875 // Function frame setup and tear down. |
872 void EnterFrame(RegList regs, intptr_t frame_space); | 876 void EnterFrame(RegList regs, intptr_t frame_space); |
873 void LeaveFrame(RegList regs); | 877 void LeaveFrame(RegList regs); |
874 void Ret(); | 878 void Ret(); |
875 void ReserveAlignedFrameSpace(intptr_t frame_space); | 879 void ReserveAlignedFrameSpace(intptr_t frame_space); |
876 | 880 |
877 // Create a frame for calling into runtime that preserves all volatile | 881 // Create a frame for calling into runtime that preserves all volatile |
878 // registers. Frame's SP is guaranteed to be correctly aligned and | 882 // registers. Frame's SP is guaranteed to be correctly aligned and |
879 // frame_space bytes are reserved under it. | 883 // frame_space bytes are reserved under it. |
880 void EnterCallRuntimeFrame(intptr_t frame_space); | 884 void EnterCallRuntimeFrame(intptr_t frame_space); |
881 void LeaveCallRuntimeFrame(); | 885 void LeaveCallRuntimeFrame(); |
882 | 886 |
883 void CallRuntime(const RuntimeEntry& entry, intptr_t argument_count); | 887 void CallRuntime(const RuntimeEntry& entry, intptr_t argument_count); |
884 | 888 |
885 // Set up a Dart frame on entry with a frame pointer and PC information to | 889 // Set up a Dart frame on entry with a frame pointer and PC information to |
886 // enable easy access to the RawInstruction object of code corresponding | 890 // enable easy access to the RawInstruction object of code corresponding |
887 // to this frame. | 891 // to this frame. |
888 void EnterDartFrame(intptr_t frame_size); | 892 void EnterDartFrame(intptr_t frame_size); |
889 void LeaveDartFrame(); | 893 void LeaveDartFrame(RestorePP restore_pp = kRestoreCallerPP); |
890 | 894 |
891 // Set up a Dart frame for a function compiled for on-stack replacement. | 895 // Set up a Dart frame for a function compiled for on-stack replacement. |
892 // The frame layout is a normal Dart frame, but the frame is partially set | 896 // The frame layout is a normal Dart frame, but the frame is partially set |
893 // up on entry (it is the frame of the unoptimized code). | 897 // up on entry (it is the frame of the unoptimized code). |
894 void EnterOsrFrame(intptr_t extra_size); | 898 void EnterOsrFrame(intptr_t extra_size); |
895 | 899 |
896 // Set up a stub frame so that the stack traversal code can easily identify | 900 // Set up a stub frame so that the stack traversal code can easily identify |
897 // a stub frame. | 901 // a stub frame. |
898 void EnterStubFrame(); | 902 void EnterStubFrame(); |
899 void LeaveStubFrame(); | 903 void LeaveStubFrame(); |
900 | 904 |
901 // Instruction pattern from entrypoint is used in Dart frame prologs | |
902 // to set up the frame and save a PC which can be used to figure out the | |
903 // RawInstruction object corresponding to the code running in the frame. | |
904 static intptr_t EntryPointToPcMarkerOffset() { | |
905 return TargetCPUFeatures::store_pc_read_offset(); | |
906 } | |
907 | |
908 // The register into which the allocation stats table is loaded with | 905 // The register into which the allocation stats table is loaded with |
909 // LoadAllocationStatsAddress should be passed to | 906 // LoadAllocationStatsAddress should be passed to |
910 // IncrementAllocationStats(WithSize) as stats_addr_reg to update the | 907 // IncrementAllocationStats(WithSize) as stats_addr_reg to update the |
911 // allocation stats. These are separate assembler macros so we can | 908 // allocation stats. These are separate assembler macros so we can |
912 // avoid a dependent load too nearby the load of the table address. | 909 // avoid a dependent load too nearby the load of the table address. |
913 void LoadAllocationStatsAddress(Register dest, | 910 void LoadAllocationStatsAddress(Register dest, |
914 intptr_t cid, | 911 intptr_t cid, |
915 bool inline_isolate = true); | 912 bool inline_isolate = true); |
916 void IncrementAllocationStats(Register stats_addr, | 913 void IncrementAllocationStats(Register stats_addr, |
917 intptr_t cid, | 914 intptr_t cid, |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
983 bool use_far_branches_; | 980 bool use_far_branches_; |
984 | 981 |
985 // If you are thinking of using one or both of these instructions directly, | 982 // If you are thinking of using one or both of these instructions directly, |
986 // instead LoadImmediate should probably be used. | 983 // instead LoadImmediate should probably be used. |
987 void movw(Register rd, uint16_t imm16, Condition cond = AL); | 984 void movw(Register rd, uint16_t imm16, Condition cond = AL); |
988 void movt(Register rd, uint16_t imm16, Condition cond = AL); | 985 void movt(Register rd, uint16_t imm16, Condition cond = AL); |
989 | 986 |
990 void BindARMv6(Label* label); | 987 void BindARMv6(Label* label); |
991 void BindARMv7(Label* label); | 988 void BindARMv7(Label* label); |
992 | 989 |
| 990 void LoadWordFromPoolOffset(Register rd, |
| 991 int32_t offset, |
| 992 Register pp, |
| 993 Condition cond = AL); |
| 994 |
993 void BranchLink(const ExternalLabel* label); | 995 void BranchLink(const ExternalLabel* label); |
994 | 996 |
995 class CodeComment : public ZoneAllocated { | 997 class CodeComment : public ZoneAllocated { |
996 public: | 998 public: |
997 CodeComment(intptr_t pc_offset, const String& comment) | 999 CodeComment(intptr_t pc_offset, const String& comment) |
998 : pc_offset_(pc_offset), comment_(comment) { } | 1000 : pc_offset_(pc_offset), comment_(comment) { } |
999 | 1001 |
1000 intptr_t pc_offset() const { return pc_offset_; } | 1002 intptr_t pc_offset() const { return pc_offset_; } |
1001 const String& comment() const { return comment_; } | 1003 const String& comment() const { return comment_; } |
1002 | 1004 |
1003 private: | 1005 private: |
1004 intptr_t pc_offset_; | 1006 intptr_t pc_offset_; |
1005 const String& comment_; | 1007 const String& comment_; |
1006 | 1008 |
1007 DISALLOW_COPY_AND_ASSIGN(CodeComment); | 1009 DISALLOW_COPY_AND_ASSIGN(CodeComment); |
1008 }; | 1010 }; |
1009 | 1011 |
1010 GrowableArray<CodeComment*> comments_; | 1012 GrowableArray<CodeComment*> comments_; |
1011 | 1013 |
1012 bool constant_pool_allowed_; | 1014 bool constant_pool_allowed_; |
1013 | 1015 |
1014 void LoadObjectHelper(Register rd, | 1016 void LoadObjectHelper(Register rd, |
1015 const Object& object, | 1017 const Object& object, |
1016 Condition cond, | 1018 Condition cond, |
1017 bool is_unique); | 1019 bool is_unique, |
| 1020 Register pp); |
1018 | 1021 |
1019 void EmitType01(Condition cond, | 1022 void EmitType01(Condition cond, |
1020 int type, | 1023 int type, |
1021 Opcode opcode, | 1024 Opcode opcode, |
1022 int set_cc, | 1025 int set_cc, |
1023 Register rn, | 1026 Register rn, |
1024 Register rd, | 1027 Register rd, |
1025 Operand o); | 1028 Operand o); |
1026 | 1029 |
1027 void EmitType5(Condition cond, int32_t offset, bool link); | 1030 void EmitType5(Condition cond, int32_t offset, bool link); |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1144 Register new_value, | 1147 Register new_value, |
1145 FieldContent old_content); | 1148 FieldContent old_content); |
1146 | 1149 |
1147 DISALLOW_ALLOCATION(); | 1150 DISALLOW_ALLOCATION(); |
1148 DISALLOW_COPY_AND_ASSIGN(Assembler); | 1151 DISALLOW_COPY_AND_ASSIGN(Assembler); |
1149 }; | 1152 }; |
1150 | 1153 |
1151 } // namespace dart | 1154 } // namespace dart |
1152 | 1155 |
1153 #endif // VM_ASSEMBLER_ARM_H_ | 1156 #endif // VM_ASSEMBLER_ARM_H_ |
OLD | NEW |