Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(270)

Side by Side Diff: runtime/vm/assembler_arm64.cc

Issue 269343010: Adds single-precision and SIMD load/store to arm64. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/assembler_arm64.h ('k') | runtime/vm/assembler_arm64_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 654 matching lines...) Expand 10 before | Expand all | Expand 10 after
665 cmn(rn, op); 665 cmn(rn, op);
666 } else { 666 } else {
667 ASSERT(rn != TMP2); 667 ASSERT(rn != TMP2);
668 LoadImmediate(TMP2, imm, pp); 668 LoadImmediate(TMP2, imm, pp);
669 cmp(rn, Operand(TMP2)); 669 cmp(rn, Operand(TMP2));
670 } 670 }
671 } 671 }
672 672
673 673
674 void Assembler::LoadFromOffset( 674 void Assembler::LoadFromOffset(
675 Register dest, Register base, int32_t offset, OperandSize sz) { 675 Register dest, Register base, int32_t offset, Register pp, OperandSize sz) {
676 if (Address::CanHoldOffset(offset, Address::Offset, sz)) { 676 if (Address::CanHoldOffset(offset, Address::Offset, sz)) {
677 ldr(dest, Address(base, offset, Address::Offset, sz), sz); 677 ldr(dest, Address(base, offset, Address::Offset, sz), sz);
678 } else { 678 } else {
679 ASSERT(base != TMP2); 679 ASSERT(base != TMP2);
680 // Since offset is 32-bits, it won't be loaded from the pool. 680 AddImmediate(TMP2, base, offset, pp);
681 AddImmediate(TMP2, base, offset, kNoPP);
682 ldr(dest, Address(TMP2), sz); 681 ldr(dest, Address(TMP2), sz);
683 } 682 }
684 } 683 }
685 684
686 685
687 void Assembler::LoadDFromOffset(VRegister dest, Register base, int32_t offset) { 686 void Assembler::LoadDFromOffset(
687 VRegister dest, Register base, int32_t offset, Register pp) {
688 if (Address::CanHoldOffset(offset, Address::Offset, kDWord)) { 688 if (Address::CanHoldOffset(offset, Address::Offset, kDWord)) {
689 fldrd(dest, Address(base, offset, Address::Offset, kDWord)); 689 fldrd(dest, Address(base, offset, Address::Offset, kDWord));
690 } else { 690 } else {
691 ASSERT(base != TMP2); 691 ASSERT(base != TMP2);
692 // Since offset is 32-bits, it won't be loaded from the pool. 692 AddImmediate(TMP2, base, offset, pp);
693 AddImmediate(TMP2, base, offset, kNoPP);
694 fldrd(dest, Address(TMP2)); 693 fldrd(dest, Address(TMP2));
695 } 694 }
696 } 695 }
697 696
698 697
698 void Assembler::LoadQFromOffset(
699 VRegister dest, Register base, int32_t offset, Register pp) {
700 if (Address::CanHoldOffset(offset, Address::Offset, kQWord)) {
701 fldrq(dest, Address(base, offset, Address::Offset, kQWord));
702 } else {
703 ASSERT(base != TMP2);
704 AddImmediate(TMP2, base, offset, pp);
705 fldrq(dest, Address(TMP2));
706 }
707 }
708
709
699 void Assembler::StoreToOffset( 710 void Assembler::StoreToOffset(
700 Register src, Register base, int32_t offset, OperandSize sz) { 711 Register src, Register base, int32_t offset, Register pp, OperandSize sz) {
701 ASSERT(base != TMP2); 712 ASSERT(base != TMP2);
702 if (Address::CanHoldOffset(offset, Address::Offset, sz)) { 713 if (Address::CanHoldOffset(offset, Address::Offset, sz)) {
703 str(src, Address(base, offset, Address::Offset, sz), sz); 714 str(src, Address(base, offset, Address::Offset, sz), sz);
704 } else { 715 } else {
705 ASSERT(src != TMP2); 716 ASSERT(src != TMP2);
706 // Since offset is 32-bits, it won't be loaded from the pool. 717 AddImmediate(TMP2, base, offset, pp);
707 AddImmediate(TMP2, base, offset, kNoPP);
708 str(src, Address(TMP2), sz); 718 str(src, Address(TMP2), sz);
709 } 719 }
710 } 720 }
711 721
712 722
713 void Assembler::StoreDToOffset(VRegister src, Register base, int32_t offset) { 723 void Assembler::StoreDToOffset(
724 VRegister src, Register base, int32_t offset, Register pp) {
714 if (Address::CanHoldOffset(offset, Address::Offset, kDWord)) { 725 if (Address::CanHoldOffset(offset, Address::Offset, kDWord)) {
715 fstrd(src, Address(base, offset, Address::Offset, kDWord)); 726 fstrd(src, Address(base, offset, Address::Offset, kDWord));
716 } else { 727 } else {
717 ASSERT(base != TMP2); 728 ASSERT(base != TMP2);
718 // Since offset is 32-bits, it won't be loaded from the pool. 729 AddImmediate(TMP2, base, offset, pp);
719 AddImmediate(TMP2, base, offset, kNoPP);
720 fstrd(src, Address(TMP2)); 730 fstrd(src, Address(TMP2));
721 } 731 }
722 } 732 }
723 733
724 734
735 void Assembler::StoreQToOffset(
736 VRegister src, Register base, int32_t offset, Register pp) {
737 if (Address::CanHoldOffset(offset, Address::Offset, kQWord)) {
738 fstrq(src, Address(base, offset, Address::Offset, kQWord));
739 } else {
740 ASSERT(base != TMP2);
741 AddImmediate(TMP2, base, offset, pp);
742 fstrq(src, Address(TMP2));
743 }
744 }
745
746
725 // Store into object. 747 // Store into object.
726 // Preserves object and value registers. 748 // Preserves object and value registers.
727 void Assembler::StoreIntoObjectFilterNoSmi(Register object, 749 void Assembler::StoreIntoObjectFilterNoSmi(Register object,
728 Register value, 750 Register value,
729 Label* no_update) { 751 Label* no_update) {
730 COMPILE_ASSERT((kNewObjectAlignmentOffset == kWordSize) && 752 COMPILE_ASSERT((kNewObjectAlignmentOffset == kWordSize) &&
731 (kOldObjectAlignmentOffset == 0), young_alignment); 753 (kOldObjectAlignmentOffset == 0), young_alignment);
732 754
733 // Write-barrier triggers if the value is in the new space (has bit set) and 755 // Write-barrier triggers if the value is in the new space (has bit set) and
734 // the object is in the old space (has bit cleared). 756 // the object is in the old space (has bit cleared).
(...skipping 12 matching lines...) Expand all
747 // For the value we are only interested in the new/old bit and the tag bit. 769 // For the value we are only interested in the new/old bit and the tag bit.
748 // And the new bit with the tag bit. The resulting bit will be 0 for a Smi. 770 // And the new bit with the tag bit. The resulting bit will be 0 for a Smi.
749 and_(TMP, value, Operand(value, LSL, kObjectAlignmentLog2 - 1)); 771 and_(TMP, value, Operand(value, LSL, kObjectAlignmentLog2 - 1));
750 // And the result with the negated space bit of the object. 772 // And the result with the negated space bit of the object.
751 bic(TMP, TMP, Operand(object)); 773 bic(TMP, TMP, Operand(object));
752 tsti(TMP, kNewObjectAlignmentOffset); 774 tsti(TMP, kNewObjectAlignmentOffset);
753 b(no_update, EQ); 775 b(no_update, EQ);
754 } 776 }
755 777
756 778
779 void Assembler::StoreIntoObjectOffset(Register object,
780 int32_t offset,
781 Register value,
782 Register pp,
783 bool can_value_be_smi) {
784 if (Address::CanHoldOffset(offset - kHeapObjectTag)) {
785 StoreIntoObject(
786 object, FieldAddress(object, offset), value, can_value_be_smi);
787 } else {
788 AddImmediate(TMP, object, offset - kHeapObjectTag, pp);
789 StoreIntoObject(object, Address(TMP), value, can_value_be_smi);
790 }
791 }
792
793
757 void Assembler::StoreIntoObject(Register object, 794 void Assembler::StoreIntoObject(Register object,
758 const Address& dest, 795 const Address& dest,
759 Register value, 796 Register value,
760 bool can_value_be_smi) { 797 bool can_value_be_smi) {
761 ASSERT(object != value); 798 ASSERT(object != value);
762 str(value, dest); 799 str(value, dest);
763 Label done; 800 Label done;
764 if (can_value_be_smi) { 801 if (can_value_be_smi) {
765 StoreIntoObjectFilter(object, value, &done); 802 StoreIntoObjectFilter(object, value, &done);
766 } else { 803 } else {
(...skipping 25 matching lines...) Expand all
792 #if defined(DEBUG) 829 #if defined(DEBUG)
793 Label done; 830 Label done;
794 StoreIntoObjectFilter(object, value, &done); 831 StoreIntoObjectFilter(object, value, &done);
795 Stop("Store buffer update is required"); 832 Stop("Store buffer update is required");
796 Bind(&done); 833 Bind(&done);
797 #endif // defined(DEBUG) 834 #endif // defined(DEBUG)
798 // No store buffer update. 835 // No store buffer update.
799 } 836 }
800 837
801 838
839 void Assembler::StoreIntoObjectOffsetNoBarrier(Register object,
840 int32_t offset,
841 Register value,
842 Register pp) {
843 if (Address::CanHoldOffset(offset - kHeapObjectTag)) {
844 StoreIntoObjectNoBarrier(object, FieldAddress(object, offset), value);
845 } else {
846 AddImmediate(TMP, object, offset - kHeapObjectTag, pp);
847 StoreIntoObjectNoBarrier(object, Address(TMP), value);
848 }
849 }
850
851
802 void Assembler::StoreIntoObjectNoBarrier(Register object, 852 void Assembler::StoreIntoObjectNoBarrier(Register object,
803 const Address& dest, 853 const Address& dest,
804 const Object& value) { 854 const Object& value) {
805 ASSERT(value.IsSmi() || value.InVMHeap() || 855 ASSERT(value.IsSmi() || value.InVMHeap() ||
806 (value.IsOld() && value.IsNotTemporaryScopedHandle())); 856 (value.IsOld() && value.IsNotTemporaryScopedHandle()));
807 // No store buffer update. 857 // No store buffer update.
808 LoadObject(TMP, value, PP); 858 LoadObject(TMP2, value, PP);
809 str(TMP, dest); 859 str(TMP2, dest);
810 } 860 }
811 861
812 862
813 void Assembler::LoadClassId(Register result, Register object) { 863 void Assembler::StoreIntoObjectOffsetNoBarrier(Register object,
864 int32_t offset,
865 const Object& value,
866 Register pp) {
867 if (Address::CanHoldOffset(offset - kHeapObjectTag)) {
868 StoreIntoObjectNoBarrier(object, FieldAddress(object, offset), value);
869 } else {
870 AddImmediate(TMP, object, offset - kHeapObjectTag, pp);
871 StoreIntoObjectNoBarrier(object, Address(TMP), value);
872 }
873 }
874
875
876 void Assembler::LoadClassId(Register result, Register object, Register pp) {
814 ASSERT(RawObject::kClassIdTagPos == 16); 877 ASSERT(RawObject::kClassIdTagPos == 16);
815 ASSERT(RawObject::kClassIdTagSize == 16); 878 ASSERT(RawObject::kClassIdTagSize == 16);
816 const intptr_t class_id_offset = Object::tags_offset() + 879 const intptr_t class_id_offset = Object::tags_offset() +
817 RawObject::kClassIdTagPos / kBitsPerByte; 880 RawObject::kClassIdTagPos / kBitsPerByte;
818 LoadFromOffset(result, object, class_id_offset - kHeapObjectTag, 881 LoadFromOffset(result, object, class_id_offset - kHeapObjectTag, pp,
819 kUnsignedHalfword); 882 kUnsignedHalfword);
820 } 883 }
821 884
822 885
823 void Assembler::LoadClassById(Register result, Register class_id) { 886 void Assembler::LoadClassById(Register result, Register class_id, Register pp) {
824 ASSERT(result != class_id); 887 ASSERT(result != class_id);
825 LoadFieldFromOffset(result, CTX, Context::isolate_offset()); 888 LoadFieldFromOffset(result, CTX, Context::isolate_offset(), pp);
826 const intptr_t table_offset_in_isolate = 889 const intptr_t table_offset_in_isolate =
827 Isolate::class_table_offset() + ClassTable::table_offset(); 890 Isolate::class_table_offset() + ClassTable::table_offset();
828 LoadFromOffset(result, result, table_offset_in_isolate); 891 LoadFromOffset(result, result, table_offset_in_isolate, pp);
829 ldr(result, Address(result, class_id, UXTX, Address::Scaled)); 892 ldr(result, Address(result, class_id, UXTX, Address::Scaled));
830 } 893 }
831 894
832 895
833 void Assembler::LoadClass(Register result, Register object) { 896 void Assembler::LoadClass(Register result, Register object, Register pp) {
834 ASSERT(object != TMP); 897 ASSERT(object != TMP);
835 LoadClassId(TMP, object); 898 LoadClassId(TMP, object, pp);
836 LoadClassById(result, TMP); 899 LoadClassById(result, TMP, pp);
837 } 900 }
838 901
839 902
840 void Assembler::CompareClassId(Register object, 903 void Assembler::CompareClassId(
841 intptr_t class_id) { 904 Register object, intptr_t class_id, Register pp) {
842 LoadClassId(TMP, object); 905 LoadClassId(TMP, object, pp);
843 CompareImmediate(TMP, class_id, PP); 906 CompareImmediate(TMP, class_id, pp);
844 } 907 }
845 908
846 909
847 // Frame entry and exit. 910 // Frame entry and exit.
848 void Assembler::ReserveAlignedFrameSpace(intptr_t frame_space) { 911 void Assembler::ReserveAlignedFrameSpace(intptr_t frame_space) {
849 // Reserve space for arguments and align frame before entering 912 // Reserve space for arguments and align frame before entering
850 // the C++ world. 913 // the C++ world.
851 AddImmediate(SP, SP, -frame_space, kNoPP); 914 AddImmediate(SP, SP, -frame_space, kNoPP);
852 if (OS::ActivationFrameAlignment() > 1) { 915 if (OS::ActivationFrameAlignment() > 1) {
853 mov(TMP, SP); // SP can't be register operand of andi. 916 mov(TMP, SP); // SP can't be register operand of andi.
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
915 978
916 // On entry to a function compiled for OSR, the caller's frame pointer, the 979 // On entry to a function compiled for OSR, the caller's frame pointer, the
917 // stack locals, and any copied parameters are already in place. The frame 980 // stack locals, and any copied parameters are already in place. The frame
918 // pointer is already set up. The PC marker is not correct for the 981 // pointer is already set up. The PC marker is not correct for the
919 // optimized function and there may be extra space for spill slots to 982 // optimized function and there may be extra space for spill slots to
920 // allocate. We must also set up the pool pointer for the function. 983 // allocate. We must also set up the pool pointer for the function.
921 void Assembler::EnterOsrFrame(intptr_t extra_size, Register new_pp) { 984 void Assembler::EnterOsrFrame(intptr_t extra_size, Register new_pp) {
922 Comment("EnterOsrFrame"); 985 Comment("EnterOsrFrame");
923 adr(TMP, -CodeSize()); 986 adr(TMP, -CodeSize());
924 987
925 StoreToOffset(TMP, FP, kPcMarkerSlotFromFp * kWordSize); 988 StoreToOffset(TMP, FP, kPcMarkerSlotFromFp * kWordSize, kNoPP);
926 989
927 // Setup pool pointer for this dart function. 990 // Setup pool pointer for this dart function.
928 if (new_pp == kNoPP) { 991 if (new_pp == kNoPP) {
929 LoadPoolPointer(PP); 992 LoadPoolPointer(PP);
930 } else { 993 } else {
931 mov(PP, new_pp); 994 mov(PP, new_pp);
932 } 995 }
933 996
934 if (extra_size > 0) { 997 if (extra_size > 0) {
935 AddImmediate(SP, SP, -extra_size, PP); 998 AddImmediate(SP, SP, -extra_size, PP);
936 } 999 }
937 } 1000 }
938 1001
939 1002
940 void Assembler::LeaveDartFrame() { 1003 void Assembler::LeaveDartFrame() {
941 // Restore and untag PP. 1004 // Restore and untag PP.
942 LoadFromOffset(PP, FP, kSavedCallerPpSlotFromFp * kWordSize); 1005 LoadFromOffset(PP, FP, kSavedCallerPpSlotFromFp * kWordSize, kNoPP);
943 sub(PP, PP, Operand(kHeapObjectTag)); 1006 sub(PP, PP, Operand(kHeapObjectTag));
944 LeaveFrame(); 1007 LeaveFrame();
945 } 1008 }
946 1009
947 1010
948 void Assembler::EnterCallRuntimeFrame(intptr_t frame_size) { 1011 void Assembler::EnterCallRuntimeFrame(intptr_t frame_size) {
949 EnterFrame(0); 1012 EnterFrame(0);
950 1013
951 // Store fpu registers with the lowest register number at the lowest 1014 // Store fpu registers with the lowest register number at the lowest
952 // address. 1015 // address.
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
1015 Push(ZR); // Push 0 in the saved PC area for stub frames. 1078 Push(ZR); // Push 0 in the saved PC area for stub frames.
1016 TagAndPushPP(); // Save caller's pool pointer 1079 TagAndPushPP(); // Save caller's pool pointer
1017 if (load_pp) { 1080 if (load_pp) {
1018 LoadPoolPointer(PP); 1081 LoadPoolPointer(PP);
1019 } 1082 }
1020 } 1083 }
1021 1084
1022 1085
1023 void Assembler::LeaveStubFrame() { 1086 void Assembler::LeaveStubFrame() {
1024 // Restore and untag PP. 1087 // Restore and untag PP.
1025 LoadFromOffset(PP, FP, kSavedCallerPpSlotFromFp * kWordSize); 1088 LoadFromOffset(PP, FP, kSavedCallerPpSlotFromFp * kWordSize, kNoPP);
1026 sub(PP, PP, Operand(kHeapObjectTag)); 1089 sub(PP, PP, Operand(kHeapObjectTag));
1027 LeaveFrame(); 1090 LeaveFrame();
1028 } 1091 }
1029 1092
1030 1093
1031 void Assembler::UpdateAllocationStats(intptr_t cid, 1094 void Assembler::UpdateAllocationStats(intptr_t cid,
1032 Register temp_reg, 1095 Register temp_reg,
1033 Register pp, 1096 Register pp,
1034 Heap::Space space) { 1097 Heap::Space space) {
1035 ASSERT(temp_reg != kNoRegister); 1098 ASSERT(temp_reg != kNoRegister);
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
1144 ASSERT(instance_size >= kHeapObjectTag); 1207 ASSERT(instance_size >= kHeapObjectTag);
1145 AddImmediate( 1208 AddImmediate(
1146 instance_reg, instance_reg, -instance_size + kHeapObjectTag, pp); 1209 instance_reg, instance_reg, -instance_size + kHeapObjectTag, pp);
1147 UpdateAllocationStats(cls.id(), temp_reg, pp); 1210 UpdateAllocationStats(cls.id(), temp_reg, pp);
1148 1211
1149 uword tags = 0; 1212 uword tags = 0;
1150 tags = RawObject::SizeTag::update(instance_size, tags); 1213 tags = RawObject::SizeTag::update(instance_size, tags);
1151 ASSERT(cls.id() != kIllegalCid); 1214 ASSERT(cls.id() != kIllegalCid);
1152 tags = RawObject::ClassIdTag::update(cls.id(), tags); 1215 tags = RawObject::ClassIdTag::update(cls.id(), tags);
1153 LoadImmediate(TMP, tags, pp); 1216 LoadImmediate(TMP, tags, pp);
1154 StoreFieldToOffset(TMP, instance_reg, Object::tags_offset()); 1217 StoreFieldToOffset(TMP, instance_reg, Object::tags_offset(), pp);
1155 } else { 1218 } else {
1156 b(failure); 1219 b(failure);
1157 } 1220 }
1158 } 1221 }
1159 1222
1160 } // namespace dart 1223 } // namespace dart
1161 1224
1162 #endif // defined TARGET_ARCH_ARM64 1225 #endif // defined TARGET_ARCH_ARM64
OLDNEW
« no previous file with comments | « runtime/vm/assembler_arm64.h ('k') | runtime/vm/assembler_arm64_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698