OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "v8.h" | 5 #include "v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_ARM64 | 7 #if V8_TARGET_ARCH_ARM64 |
8 | 8 |
9 #include "bootstrapper.h" | 9 #include "bootstrapper.h" |
10 #include "codegen.h" | 10 #include "codegen.h" |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 LogicalImmediate(rd, rn, n, imm_s, imm_r, op); | 117 LogicalImmediate(rd, rn, n, imm_s, imm_r, op); |
118 } else { | 118 } else { |
119 // Immediate can't be encoded: synthesize using move immediate. | 119 // Immediate can't be encoded: synthesize using move immediate. |
120 Register temp = temps.AcquireSameSizeAs(rn); | 120 Register temp = temps.AcquireSameSizeAs(rn); |
121 Mov(temp, immediate); | 121 Mov(temp, immediate); |
122 if (rd.Is(csp)) { | 122 if (rd.Is(csp)) { |
123 // If rd is the stack pointer we cannot use it as the destination | 123 // If rd is the stack pointer we cannot use it as the destination |
124 // register so we use the temp register as an intermediate again. | 124 // register so we use the temp register as an intermediate again. |
125 Logical(temp, rn, temp, op); | 125 Logical(temp, rn, temp, op); |
126 Mov(csp, temp); | 126 Mov(csp, temp); |
| 127 AssertStackConsistency(); |
127 } else { | 128 } else { |
128 Logical(rd, rn, temp, op); | 129 Logical(rd, rn, temp, op); |
129 } | 130 } |
130 } | 131 } |
131 | 132 |
132 } else if (operand.IsExtendedRegister()) { | 133 } else if (operand.IsExtendedRegister()) { |
133 ASSERT(operand.reg().SizeInBits() <= rd.SizeInBits()); | 134 ASSERT(operand.reg().SizeInBits() <= rd.SizeInBits()); |
134 // Add/sub extended supports shift <= 4. We want to support exactly the | 135 // Add/sub extended supports shift <= 4. We want to support exactly the |
135 // same modes here. | 136 // same modes here. |
136 ASSERT(operand.shift_amount() <= 4); | 137 ASSERT(operand.shift_amount() <= 4); |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
224 movk(temp, imm16, 16 * i); | 225 movk(temp, imm16, 16 * i); |
225 } | 226 } |
226 } | 227 } |
227 } | 228 } |
228 ASSERT(first_mov_done); | 229 ASSERT(first_mov_done); |
229 | 230 |
230 // Move the temporary if the original destination register was the stack | 231 // Move the temporary if the original destination register was the stack |
231 // pointer. | 232 // pointer. |
232 if (rd.IsSP()) { | 233 if (rd.IsSP()) { |
233 mov(rd, temp); | 234 mov(rd, temp); |
| 235 AssertStackConsistency(); |
234 } | 236 } |
235 } | 237 } |
236 } | 238 } |
237 | 239 |
238 | 240 |
239 void MacroAssembler::Mov(const Register& rd, | 241 void MacroAssembler::Mov(const Register& rd, |
240 const Operand& operand, | 242 const Operand& operand, |
241 DiscardMoveMode discard_mode) { | 243 DiscardMoveMode discard_mode) { |
242 ASSERT(allow_macro_instructions_); | 244 ASSERT(allow_macro_instructions_); |
243 ASSERT(!rd.IsZero()); | 245 ASSERT(!rd.IsZero()); |
(...skipping 516 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
760 // Abstracted stack operations. | 762 // Abstracted stack operations. |
761 | 763 |
762 | 764 |
763 void MacroAssembler::Push(const CPURegister& src0, const CPURegister& src1, | 765 void MacroAssembler::Push(const CPURegister& src0, const CPURegister& src1, |
764 const CPURegister& src2, const CPURegister& src3) { | 766 const CPURegister& src2, const CPURegister& src3) { |
765 ASSERT(AreSameSizeAndType(src0, src1, src2, src3)); | 767 ASSERT(AreSameSizeAndType(src0, src1, src2, src3)); |
766 | 768 |
767 int count = 1 + src1.IsValid() + src2.IsValid() + src3.IsValid(); | 769 int count = 1 + src1.IsValid() + src2.IsValid() + src3.IsValid(); |
768 int size = src0.SizeInBytes(); | 770 int size = src0.SizeInBytes(); |
769 | 771 |
770 PrepareForPush(count, size); | 772 PushPreamble(count, size); |
771 PushHelper(count, size, src0, src1, src2, src3); | 773 PushHelper(count, size, src0, src1, src2, src3); |
772 } | 774 } |
773 | 775 |
774 | 776 |
775 void MacroAssembler::Push(const CPURegister& src0, const CPURegister& src1, | 777 void MacroAssembler::Push(const CPURegister& src0, const CPURegister& src1, |
776 const CPURegister& src2, const CPURegister& src3, | 778 const CPURegister& src2, const CPURegister& src3, |
777 const CPURegister& src4, const CPURegister& src5, | 779 const CPURegister& src4, const CPURegister& src5, |
778 const CPURegister& src6, const CPURegister& src7) { | 780 const CPURegister& src6, const CPURegister& src7) { |
779 ASSERT(AreSameSizeAndType(src0, src1, src2, src3, src4, src5, src6, src7)); | 781 ASSERT(AreSameSizeAndType(src0, src1, src2, src3, src4, src5, src6, src7)); |
780 | 782 |
781 int count = 5 + src5.IsValid() + src6.IsValid() + src6.IsValid(); | 783 int count = 5 + src5.IsValid() + src6.IsValid() + src6.IsValid(); |
782 int size = src0.SizeInBytes(); | 784 int size = src0.SizeInBytes(); |
783 | 785 |
784 PrepareForPush(count, size); | 786 PushPreamble(count, size); |
785 PushHelper(4, size, src0, src1, src2, src3); | 787 PushHelper(4, size, src0, src1, src2, src3); |
786 PushHelper(count - 4, size, src4, src5, src6, src7); | 788 PushHelper(count - 4, size, src4, src5, src6, src7); |
787 } | 789 } |
788 | 790 |
789 | 791 |
790 void MacroAssembler::Pop(const CPURegister& dst0, const CPURegister& dst1, | 792 void MacroAssembler::Pop(const CPURegister& dst0, const CPURegister& dst1, |
791 const CPURegister& dst2, const CPURegister& dst3) { | 793 const CPURegister& dst2, const CPURegister& dst3) { |
792 // It is not valid to pop into the same register more than once in one | 794 // It is not valid to pop into the same register more than once in one |
793 // instruction, not even into the zero register. | 795 // instruction, not even into the zero register. |
794 ASSERT(!AreAliased(dst0, dst1, dst2, dst3)); | 796 ASSERT(!AreAliased(dst0, dst1, dst2, dst3)); |
795 ASSERT(AreSameSizeAndType(dst0, dst1, dst2, dst3)); | 797 ASSERT(AreSameSizeAndType(dst0, dst1, dst2, dst3)); |
796 ASSERT(dst0.IsValid()); | 798 ASSERT(dst0.IsValid()); |
797 | 799 |
798 int count = 1 + dst1.IsValid() + dst2.IsValid() + dst3.IsValid(); | 800 int count = 1 + dst1.IsValid() + dst2.IsValid() + dst3.IsValid(); |
799 int size = dst0.SizeInBytes(); | 801 int size = dst0.SizeInBytes(); |
800 | 802 |
801 PrepareForPop(count, size); | |
802 PopHelper(count, size, dst0, dst1, dst2, dst3); | 803 PopHelper(count, size, dst0, dst1, dst2, dst3); |
803 | 804 PopPostamble(count, size); |
804 if (!csp.Is(StackPointer()) && emit_debug_code()) { | |
805 // It is safe to leave csp where it is when unwinding the JavaScript stack, | |
806 // but if we keep it matching StackPointer, the simulator can detect memory | |
807 // accesses in the now-free part of the stack. | |
808 Mov(csp, StackPointer()); | |
809 } | |
810 } | 805 } |
811 | 806 |
812 | 807 |
813 void MacroAssembler::PushPopQueue::PushQueued() { | 808 void MacroAssembler::PushPopQueue::PushQueued() { |
814 if (queued_.empty()) return; | 809 if (queued_.empty()) return; |
815 | 810 |
816 masm_->PrepareForPush(size_); | 811 masm_->PushPreamble(size_); |
817 | 812 |
818 int count = queued_.size(); | 813 int count = queued_.size(); |
819 int index = 0; | 814 int index = 0; |
820 while (index < count) { | 815 while (index < count) { |
821 // PushHelper can only handle registers with the same size and type, and it | 816 // PushHelper can only handle registers with the same size and type, and it |
822 // can handle only four at a time. Batch them up accordingly. | 817 // can handle only four at a time. Batch them up accordingly. |
823 CPURegister batch[4] = {NoReg, NoReg, NoReg, NoReg}; | 818 CPURegister batch[4] = {NoReg, NoReg, NoReg, NoReg}; |
824 int batch_index = 0; | 819 int batch_index = 0; |
825 do { | 820 do { |
826 batch[batch_index++] = queued_[index++]; | 821 batch[batch_index++] = queued_[index++]; |
827 } while ((batch_index < 4) && (index < count) && | 822 } while ((batch_index < 4) && (index < count) && |
828 batch[0].IsSameSizeAndType(queued_[index])); | 823 batch[0].IsSameSizeAndType(queued_[index])); |
829 | 824 |
830 masm_->PushHelper(batch_index, batch[0].SizeInBytes(), | 825 masm_->PushHelper(batch_index, batch[0].SizeInBytes(), |
831 batch[0], batch[1], batch[2], batch[3]); | 826 batch[0], batch[1], batch[2], batch[3]); |
832 } | 827 } |
833 | 828 |
834 queued_.clear(); | 829 queued_.clear(); |
835 } | 830 } |
836 | 831 |
837 | 832 |
838 void MacroAssembler::PushPopQueue::PopQueued() { | 833 void MacroAssembler::PushPopQueue::PopQueued() { |
839 if (queued_.empty()) return; | 834 if (queued_.empty()) return; |
840 | 835 |
841 masm_->PrepareForPop(size_); | |
842 | |
843 int count = queued_.size(); | 836 int count = queued_.size(); |
844 int index = 0; | 837 int index = 0; |
845 while (index < count) { | 838 while (index < count) { |
846 // PopHelper can only handle registers with the same size and type, and it | 839 // PopHelper can only handle registers with the same size and type, and it |
847 // can handle only four at a time. Batch them up accordingly. | 840 // can handle only four at a time. Batch them up accordingly. |
848 CPURegister batch[4] = {NoReg, NoReg, NoReg, NoReg}; | 841 CPURegister batch[4] = {NoReg, NoReg, NoReg, NoReg}; |
849 int batch_index = 0; | 842 int batch_index = 0; |
850 do { | 843 do { |
851 batch[batch_index++] = queued_[index++]; | 844 batch[batch_index++] = queued_[index++]; |
852 } while ((batch_index < 4) && (index < count) && | 845 } while ((batch_index < 4) && (index < count) && |
853 batch[0].IsSameSizeAndType(queued_[index])); | 846 batch[0].IsSameSizeAndType(queued_[index])); |
854 | 847 |
855 masm_->PopHelper(batch_index, batch[0].SizeInBytes(), | 848 masm_->PopHelper(batch_index, batch[0].SizeInBytes(), |
856 batch[0], batch[1], batch[2], batch[3]); | 849 batch[0], batch[1], batch[2], batch[3]); |
857 } | 850 } |
858 | 851 |
| 852 masm_->PopPostamble(size_); |
859 queued_.clear(); | 853 queued_.clear(); |
860 } | 854 } |
861 | 855 |
862 | 856 |
863 void MacroAssembler::PushCPURegList(CPURegList registers) { | 857 void MacroAssembler::PushCPURegList(CPURegList registers) { |
864 int size = registers.RegisterSizeInBytes(); | 858 int size = registers.RegisterSizeInBytes(); |
865 | 859 |
866 PrepareForPush(registers.Count(), size); | 860 PushPreamble(registers.Count(), size); |
867 // Push up to four registers at a time because if the current stack pointer is | 861 // Push up to four registers at a time because if the current stack pointer is |
868 // csp and reg_size is 32, registers must be pushed in blocks of four in order | 862 // csp and reg_size is 32, registers must be pushed in blocks of four in order |
869 // to maintain the 16-byte alignment for csp. | 863 // to maintain the 16-byte alignment for csp. |
870 while (!registers.IsEmpty()) { | 864 while (!registers.IsEmpty()) { |
871 int count_before = registers.Count(); | 865 int count_before = registers.Count(); |
872 const CPURegister& src0 = registers.PopHighestIndex(); | 866 const CPURegister& src0 = registers.PopHighestIndex(); |
873 const CPURegister& src1 = registers.PopHighestIndex(); | 867 const CPURegister& src1 = registers.PopHighestIndex(); |
874 const CPURegister& src2 = registers.PopHighestIndex(); | 868 const CPURegister& src2 = registers.PopHighestIndex(); |
875 const CPURegister& src3 = registers.PopHighestIndex(); | 869 const CPURegister& src3 = registers.PopHighestIndex(); |
876 int count = count_before - registers.Count(); | 870 int count = count_before - registers.Count(); |
877 PushHelper(count, size, src0, src1, src2, src3); | 871 PushHelper(count, size, src0, src1, src2, src3); |
878 } | 872 } |
879 } | 873 } |
880 | 874 |
881 | 875 |
882 void MacroAssembler::PopCPURegList(CPURegList registers) { | 876 void MacroAssembler::PopCPURegList(CPURegList registers) { |
883 int size = registers.RegisterSizeInBytes(); | 877 int size = registers.RegisterSizeInBytes(); |
884 | 878 |
885 PrepareForPop(registers.Count(), size); | |
886 // Pop up to four registers at a time because if the current stack pointer is | 879 // Pop up to four registers at a time because if the current stack pointer is |
887 // csp and reg_size is 32, registers must be pushed in blocks of four in | 880 // csp and reg_size is 32, registers must be pushed in blocks of four in |
888 // order to maintain the 16-byte alignment for csp. | 881 // order to maintain the 16-byte alignment for csp. |
889 while (!registers.IsEmpty()) { | 882 while (!registers.IsEmpty()) { |
890 int count_before = registers.Count(); | 883 int count_before = registers.Count(); |
891 const CPURegister& dst0 = registers.PopLowestIndex(); | 884 const CPURegister& dst0 = registers.PopLowestIndex(); |
892 const CPURegister& dst1 = registers.PopLowestIndex(); | 885 const CPURegister& dst1 = registers.PopLowestIndex(); |
893 const CPURegister& dst2 = registers.PopLowestIndex(); | 886 const CPURegister& dst2 = registers.PopLowestIndex(); |
894 const CPURegister& dst3 = registers.PopLowestIndex(); | 887 const CPURegister& dst3 = registers.PopLowestIndex(); |
895 int count = count_before - registers.Count(); | 888 int count = count_before - registers.Count(); |
896 PopHelper(count, size, dst0, dst1, dst2, dst3); | 889 PopHelper(count, size, dst0, dst1, dst2, dst3); |
897 } | 890 } |
898 | 891 PopPostamble(registers.Count(), size); |
899 if (!csp.Is(StackPointer()) && emit_debug_code()) { | |
900 // It is safe to leave csp where it is when unwinding the JavaScript stack, | |
901 // but if we keep it matching StackPointer, the simulator can detect memory | |
902 // accesses in the now-free part of the stack. | |
903 Mov(csp, StackPointer()); | |
904 } | |
905 } | 892 } |
906 | 893 |
907 | 894 |
908 void MacroAssembler::PushMultipleTimes(CPURegister src, int count) { | 895 void MacroAssembler::PushMultipleTimes(CPURegister src, int count) { |
909 int size = src.SizeInBytes(); | 896 int size = src.SizeInBytes(); |
910 | 897 |
911 PrepareForPush(count, size); | 898 PushPreamble(count, size); |
912 | 899 |
913 if (FLAG_optimize_for_size && count > 8) { | 900 if (FLAG_optimize_for_size && count > 8) { |
914 UseScratchRegisterScope temps(this); | 901 UseScratchRegisterScope temps(this); |
915 Register temp = temps.AcquireX(); | 902 Register temp = temps.AcquireX(); |
916 | 903 |
917 Label loop; | 904 Label loop; |
918 __ Mov(temp, count / 2); | 905 __ Mov(temp, count / 2); |
919 __ Bind(&loop); | 906 __ Bind(&loop); |
920 PushHelper(2, size, src, src, NoReg, NoReg); | 907 PushHelper(2, size, src, src, NoReg, NoReg); |
921 __ Subs(temp, temp, 1); | 908 __ Subs(temp, temp, 1); |
(...skipping 15 matching lines...) Expand all Loading... |
937 } | 924 } |
938 if (count == 1) { | 925 if (count == 1) { |
939 PushHelper(1, size, src, NoReg, NoReg, NoReg); | 926 PushHelper(1, size, src, NoReg, NoReg, NoReg); |
940 count -= 1; | 927 count -= 1; |
941 } | 928 } |
942 ASSERT(count == 0); | 929 ASSERT(count == 0); |
943 } | 930 } |
944 | 931 |
945 | 932 |
946 void MacroAssembler::PushMultipleTimes(CPURegister src, Register count) { | 933 void MacroAssembler::PushMultipleTimes(CPURegister src, Register count) { |
947 PrepareForPush(Operand(count, UXTW, WhichPowerOf2(src.SizeInBytes()))); | 934 PushPreamble(Operand(count, UXTW, WhichPowerOf2(src.SizeInBytes()))); |
948 | 935 |
949 UseScratchRegisterScope temps(this); | 936 UseScratchRegisterScope temps(this); |
950 Register temp = temps.AcquireSameSizeAs(count); | 937 Register temp = temps.AcquireSameSizeAs(count); |
951 | 938 |
952 if (FLAG_optimize_for_size) { | 939 if (FLAG_optimize_for_size) { |
953 Label loop, done; | 940 Label loop, done; |
954 | 941 |
955 Subs(temp, count, 1); | 942 Subs(temp, count, 1); |
956 B(mi, &done); | 943 B(mi, &done); |
957 | 944 |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1063 // for csp at all times. | 1050 // for csp at all times. |
1064 ldp(dst2, dst3, MemOperand(StackPointer(), 2 * size)); | 1051 ldp(dst2, dst3, MemOperand(StackPointer(), 2 * size)); |
1065 ldp(dst0, dst1, MemOperand(StackPointer(), 4 * size, PostIndex)); | 1052 ldp(dst0, dst1, MemOperand(StackPointer(), 4 * size, PostIndex)); |
1066 break; | 1053 break; |
1067 default: | 1054 default: |
1068 UNREACHABLE(); | 1055 UNREACHABLE(); |
1069 } | 1056 } |
1070 } | 1057 } |
1071 | 1058 |
1072 | 1059 |
1073 void MacroAssembler::PrepareForPush(Operand total_size) { | 1060 void MacroAssembler::PushPreamble(Operand total_size) { |
1074 // TODO(jbramley): This assertion generates too much code in some debug tests. | 1061 // TODO(jbramley): This assertion generates too much code in some debug tests. |
1075 // AssertStackConsistency(); | 1062 // AssertStackConsistency(); |
1076 if (csp.Is(StackPointer())) { | 1063 if (csp.Is(StackPointer())) { |
1077 // If the current stack pointer is csp, then it must be aligned to 16 bytes | 1064 // If the current stack pointer is csp, then it must be aligned to 16 bytes |
1078 // on entry and the total size of the specified registers must also be a | 1065 // on entry and the total size of the specified registers must also be a |
1079 // multiple of 16 bytes. | 1066 // multiple of 16 bytes. |
1080 if (total_size.IsImmediate()) { | 1067 if (total_size.IsImmediate()) { |
1081 ASSERT((total_size.immediate() % 16) == 0); | 1068 ASSERT((total_size.immediate() % 16) == 0); |
1082 } | 1069 } |
1083 | 1070 |
1084 // Don't check access size for non-immediate sizes. It's difficult to do | 1071 // Don't check access size for non-immediate sizes. It's difficult to do |
1085 // well, and it will be caught by hardware (or the simulator) anyway. | 1072 // well, and it will be caught by hardware (or the simulator) anyway. |
1086 } else { | 1073 } else { |
1087 // Even if the current stack pointer is not the system stack pointer (csp), | 1074 // Even if the current stack pointer is not the system stack pointer (csp), |
1088 // the system stack pointer will still be modified in order to comply with | 1075 // the system stack pointer will still be modified in order to comply with |
1089 // ABI rules about accessing memory below the system stack pointer. | 1076 // ABI rules about accessing memory below the system stack pointer. |
1090 BumpSystemStackPointer(total_size); | 1077 BumpSystemStackPointer(total_size); |
1091 } | 1078 } |
1092 } | 1079 } |
1093 | 1080 |
1094 | 1081 |
1095 void MacroAssembler::PrepareForPop(Operand total_size) { | 1082 void MacroAssembler::PopPostamble(Operand total_size) { |
1096 AssertStackConsistency(); | 1083 AssertStackConsistency(); |
1097 if (csp.Is(StackPointer())) { | 1084 if (csp.Is(StackPointer())) { |
1098 // If the current stack pointer is csp, then it must be aligned to 16 bytes | 1085 // If the current stack pointer is csp, then it must be aligned to 16 bytes |
1099 // on entry and the total size of the specified registers must also be a | 1086 // on entry and the total size of the specified registers must also be a |
1100 // multiple of 16 bytes. | 1087 // multiple of 16 bytes. |
1101 if (total_size.IsImmediate()) { | 1088 if (total_size.IsImmediate()) { |
1102 ASSERT((total_size.immediate() % 16) == 0); | 1089 ASSERT((total_size.immediate() % 16) == 0); |
1103 } | 1090 } |
1104 | 1091 |
1105 // Don't check access size for non-immediate sizes. It's difficult to do | 1092 // Don't check access size for non-immediate sizes. It's difficult to do |
1106 // well, and it will be caught by hardware (or the simulator) anyway. | 1093 // well, and it will be caught by hardware (or the simulator) anyway. |
| 1094 } else if (emit_debug_code()) { |
| 1095 // It is safe to leave csp where it is when unwinding the JavaScript stack, |
| 1096 // but if we keep it matching StackPointer, the simulator can detect memory |
| 1097 // accesses in the now-free part of the stack. |
| 1098 SyncSystemStackPointer(); |
1107 } | 1099 } |
1108 } | 1100 } |
1109 | 1101 |
1110 | 1102 |
1111 void MacroAssembler::Poke(const CPURegister& src, const Operand& offset) { | 1103 void MacroAssembler::Poke(const CPURegister& src, const Operand& offset) { |
1112 if (offset.IsImmediate()) { | 1104 if (offset.IsImmediate()) { |
1113 ASSERT(offset.immediate() >= 0); | 1105 ASSERT(offset.immediate() >= 0); |
1114 } else if (emit_debug_code()) { | 1106 } else if (emit_debug_code()) { |
1115 Cmp(xzr, offset); | 1107 Cmp(xzr, offset); |
1116 Check(le, kStackAccessBelowStackPointer); | 1108 Check(le, kStackAccessBelowStackPointer); |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1193 | 1185 |
1194 ldp(d8, d9, tos); | 1186 ldp(d8, d9, tos); |
1195 ldp(d10, d11, tos); | 1187 ldp(d10, d11, tos); |
1196 ldp(d12, d13, tos); | 1188 ldp(d12, d13, tos); |
1197 ldp(d14, d15, tos); | 1189 ldp(d14, d15, tos); |
1198 } | 1190 } |
1199 | 1191 |
1200 | 1192 |
1201 void MacroAssembler::AssertStackConsistency() { | 1193 void MacroAssembler::AssertStackConsistency() { |
1202 if (emit_debug_code()) { | 1194 if (emit_debug_code()) { |
1203 if (csp.Is(StackPointer())) { | 1195 if (csp.Is(StackPointer()) || CpuFeatures::IsSupported(ALWAYS_ALIGN_CSP)) { |
1204 // We can't check the alignment of csp without using a scratch register | 1196 // Always check the alignment of csp if ALWAYS_ALIGN_CSP is true, since it |
1205 // (or clobbering the flags), but the processor (or simulator) will abort | 1197 // could have been bumped even if it is not the stack pointer. We can't |
1206 // if it is not properly aligned during a load. | 1198 // check the alignment of csp without using a scratch register (or |
| 1199 // clobbering the flags), but the processor (or simulator) will abort if |
| 1200 // it is not properly aligned during a load. |
1207 ldr(xzr, MemOperand(csp, 0)); | 1201 ldr(xzr, MemOperand(csp, 0)); |
1208 } else if (FLAG_enable_slow_asserts) { | 1202 } else if (FLAG_enable_slow_asserts && !csp.Is(StackPointer())) { |
1209 Label ok; | 1203 Label ok; |
1210 // Check that csp <= StackPointer(), preserving all registers and NZCV. | 1204 // Check that csp <= StackPointer(), preserving all registers and NZCV. |
1211 sub(StackPointer(), csp, StackPointer()); | 1205 sub(StackPointer(), csp, StackPointer()); |
1212 cbz(StackPointer(), &ok); // Ok if csp == StackPointer(). | 1206 cbz(StackPointer(), &ok); // Ok if csp == StackPointer(). |
1213 tbnz(StackPointer(), kXSignBit, &ok); // Ok if csp < StackPointer(). | 1207 tbnz(StackPointer(), kXSignBit, &ok); // Ok if csp < StackPointer(). |
1214 | 1208 |
1215 Abort(kTheCurrentStackPointerIsBelowCsp); | 1209 Abort(kTheCurrentStackPointerIsBelowCsp); |
1216 | 1210 |
1217 bind(&ok); | 1211 bind(&ok); |
1218 // Restore StackPointer(). | 1212 // Restore StackPointer(). |
(...skipping 4016 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5235 } | 5229 } |
5236 } | 5230 } |
5237 | 5231 |
5238 | 5232 |
5239 #undef __ | 5233 #undef __ |
5240 | 5234 |
5241 | 5235 |
5242 } } // namespace v8::internal | 5236 } } // namespace v8::internal |
5243 | 5237 |
5244 #endif // V8_TARGET_ARCH_ARM64 | 5238 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |