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 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. |
6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
7 | 7 |
8 #include "vm/intrinsifier.h" | 8 #include "vm/intrinsifier.h" |
9 | 9 |
10 #include "vm/assembler.h" | 10 #include "vm/assembler.h" |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
254 /* R4: allocation stats address */ \ | 254 /* R4: allocation stats address */ \ |
255 /* R6, R7: zero. */ \ | 255 /* R6, R7: zero. */ \ |
256 /* data area to be initialized. */ \ | 256 /* data area to be initialized. */ \ |
257 __ LoadImmediate(R6, 0); \ | 257 __ LoadImmediate(R6, 0); \ |
258 __ mov(R7, Operand(R6)); \ | 258 __ mov(R7, Operand(R6)); \ |
259 __ AddImmediate(R3, R0, sizeof(Raw##type_name) - 1); \ | 259 __ AddImmediate(R3, R0, sizeof(Raw##type_name) - 1); \ |
260 Label init_loop; \ | 260 Label init_loop; \ |
261 __ Bind(&init_loop); \ | 261 __ Bind(&init_loop); \ |
262 __ AddImmediate(R3, 2 * kWordSize); \ | 262 __ AddImmediate(R3, 2 * kWordSize); \ |
263 __ cmp(R3, Operand(R1)); \ | 263 __ cmp(R3, Operand(R1)); \ |
264 __ strd(R6, Address(R3, -2 * kWordSize), LS); \ | 264 __ strd(R6, R3, -2 * kWordSize, LS); \ |
265 __ b(&init_loop, CC); \ | 265 __ b(&init_loop, CC); \ |
266 __ str(R6, Address(R3, -2 * kWordSize), HI); \ | 266 __ str(R6, Address(R3, -2 * kWordSize), HI); \ |
267 \ | 267 \ |
268 __ IncrementAllocationStatsWithSize(R4, R2, cid, space); \ | 268 __ IncrementAllocationStatsWithSize(R4, R2, cid, space); \ |
269 __ Ret(); \ | 269 __ Ret(); \ |
270 __ Bind(&fall_through); \ | 270 __ Bind(&fall_through); \ |
271 | 271 |
272 | 272 |
273 static int GetScaleFactor(intptr_t size) { | 273 static int GetScaleFactor(intptr_t size) { |
274 switch (size) { | 274 switch (size) { |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
341 Label fall_through; | 341 Label fall_through; |
342 TestBothArgumentsSmis(assembler, &fall_through); | 342 TestBothArgumentsSmis(assembler, &fall_through); |
343 __ subs(R0, R1, Operand(R0)); // Subtract. | 343 __ subs(R0, R1, Operand(R0)); // Subtract. |
344 __ bx(LR, VC); // Return if no overflow. | 344 __ bx(LR, VC); // Return if no overflow. |
345 // Otherwise fall through. | 345 // Otherwise fall through. |
346 __ Bind(&fall_through); | 346 __ Bind(&fall_through); |
347 } | 347 } |
348 | 348 |
349 | 349 |
350 void Intrinsifier::Integer_mulFromInteger(Assembler* assembler) { | 350 void Intrinsifier::Integer_mulFromInteger(Assembler* assembler) { |
351 if (TargetCPUFeatures::arm_version() == ARMv7) { | 351 Label fall_through; |
352 Label fall_through; | 352 TestBothArgumentsSmis(assembler, &fall_through); // checks two smis |
353 TestBothArgumentsSmis(assembler, &fall_through); // checks two smis | 353 __ SmiUntag(R0); // Untags R6. We only want result shifted by one. |
354 __ SmiUntag(R0); // Untags R6. We only want result shifted by one. | 354 __ smull(R0, IP, R0, R1); // IP:R0 <- R0 * R1. |
355 __ smull(R0, IP, R0, R1); // IP:R0 <- R0 * R1. | 355 __ cmp(IP, Operand(R0, ASR, 31)); |
356 __ cmp(IP, Operand(R0, ASR, 31)); | 356 __ bx(LR, EQ); |
357 __ bx(LR, EQ); | 357 __ Bind(&fall_through); // Fall through on overflow. |
358 __ Bind(&fall_through); // Fall through on overflow. | |
359 } else if (TargetCPUFeatures::can_divide()) { | |
360 Label fall_through; | |
361 TestBothArgumentsSmis(assembler, &fall_through); // checks two smis | |
362 __ SmiUntag(R0); // Untags R6. We only want result shifted by one. | |
363 __ CheckMultSignedOverflow(R0, R1, IP, D0, D1, &fall_through); | |
364 __ mul(R0, R0, R1); | |
365 __ Ret(); | |
366 __ Bind(&fall_through); // Fall through on overflow. | |
367 } | |
368 } | 358 } |
369 | 359 |
370 | 360 |
371 void Intrinsifier::Integer_mul(Assembler* assembler) { | 361 void Intrinsifier::Integer_mul(Assembler* assembler) { |
372 Integer_mulFromInteger(assembler); | 362 Integer_mulFromInteger(assembler); |
373 } | 363 } |
374 | 364 |
375 | 365 |
376 // Optimizations: | 366 // Optimizations: |
377 // - result is 0 if: | 367 // - result is 0 if: |
(...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
799 // TODO(sra): Implement as word-length - CLZ. | 789 // TODO(sra): Implement as word-length - CLZ. |
800 } | 790 } |
801 | 791 |
802 | 792 |
803 void Intrinsifier::Bigint_absAdd(Assembler* assembler) { | 793 void Intrinsifier::Bigint_absAdd(Assembler* assembler) { |
804 // static void _absAdd(Uint32List digits, int used, | 794 // static void _absAdd(Uint32List digits, int used, |
805 // Uint32List a_digits, int a_used, | 795 // Uint32List a_digits, int a_used, |
806 // Uint32List r_digits) | 796 // Uint32List r_digits) |
807 | 797 |
808 // R2 = used, R3 = digits | 798 // R2 = used, R3 = digits |
809 __ ldrd(R2, Address(SP, 3 * kWordSize)); | 799 __ ldrd(R2, SP, 3 * kWordSize); |
810 // R3 = &digits[0] | 800 // R3 = &digits[0] |
811 __ add(R3, R3, Operand(TypedData::data_offset() - kHeapObjectTag)); | 801 __ add(R3, R3, Operand(TypedData::data_offset() - kHeapObjectTag)); |
812 | 802 |
813 // R4 = a_used, R5 = a_digits | 803 // R4 = a_used, R5 = a_digits |
814 __ ldrd(R4, Address(SP, 1 * kWordSize)); | 804 __ ldrd(R4, SP, 1 * kWordSize); |
815 // R5 = &a_digits[0] | 805 // R5 = &a_digits[0] |
816 __ add(R5, R5, Operand(TypedData::data_offset() - kHeapObjectTag)); | 806 __ add(R5, R5, Operand(TypedData::data_offset() - kHeapObjectTag)); |
817 | 807 |
818 // R6 = r_digits | 808 // R6 = r_digits |
819 __ ldr(R6, Address(SP, 0 * kWordSize)); | 809 __ ldr(R6, Address(SP, 0 * kWordSize)); |
820 // R6 = &r_digits[0] | 810 // R6 = &r_digits[0] |
821 __ add(R6, R6, Operand(TypedData::data_offset() - kHeapObjectTag)); | 811 __ add(R6, R6, Operand(TypedData::data_offset() - kHeapObjectTag)); |
822 | 812 |
823 // R7 = &digits[a_used >> 1], a_used is Smi. | 813 // R7 = &digits[a_used >> 1], a_used is Smi. |
824 __ add(R7, R3, Operand(R4, LSL, 1)); | 814 __ add(R7, R3, Operand(R4, LSL, 1)); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
859 __ Ret(); | 849 __ Ret(); |
860 } | 850 } |
861 | 851 |
862 | 852 |
863 void Intrinsifier::Bigint_absSub(Assembler* assembler) { | 853 void Intrinsifier::Bigint_absSub(Assembler* assembler) { |
864 // static void _absSub(Uint32List digits, int used, | 854 // static void _absSub(Uint32List digits, int used, |
865 // Uint32List a_digits, int a_used, | 855 // Uint32List a_digits, int a_used, |
866 // Uint32List r_digits) | 856 // Uint32List r_digits) |
867 | 857 |
868 // R2 = used, R3 = digits | 858 // R2 = used, R3 = digits |
869 __ ldrd(R2, Address(SP, 3 * kWordSize)); | 859 __ ldrd(R2, SP, 3 * kWordSize); |
870 // R3 = &digits[0] | 860 // R3 = &digits[0] |
871 __ add(R3, R3, Operand(TypedData::data_offset() - kHeapObjectTag)); | 861 __ add(R3, R3, Operand(TypedData::data_offset() - kHeapObjectTag)); |
872 | 862 |
873 // R4 = a_used, R5 = a_digits | 863 // R4 = a_used, R5 = a_digits |
874 __ ldrd(R4, Address(SP, 1 * kWordSize)); | 864 __ ldrd(R4, SP, 1 * kWordSize); |
875 // R5 = &a_digits[0] | 865 // R5 = &a_digits[0] |
876 __ add(R5, R5, Operand(TypedData::data_offset() - kHeapObjectTag)); | 866 __ add(R5, R5, Operand(TypedData::data_offset() - kHeapObjectTag)); |
877 | 867 |
878 // R6 = r_digits | 868 // R6 = r_digits |
879 __ ldr(R6, Address(SP, 0 * kWordSize)); | 869 __ ldr(R6, Address(SP, 0 * kWordSize)); |
880 // R6 = &r_digits[0] | 870 // R6 = &r_digits[0] |
881 __ add(R6, R6, Operand(TypedData::data_offset() - kHeapObjectTag)); | 871 __ add(R6, R6, Operand(TypedData::data_offset() - kHeapObjectTag)); |
882 | 872 |
883 // R7 = &digits[a_used >> 1], a_used is Smi. | 873 // R7 = &digits[a_used >> 1], a_used is Smi. |
884 __ add(R7, R3, Operand(R4, LSL, 1)); | 874 __ add(R7, R3, Operand(R4, LSL, 1)); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
942 // while (c != 0) { | 932 // while (c != 0) { |
943 // uint64_t t = *ajp + c; | 933 // uint64_t t = *ajp + c; |
944 // *ajp++ = low32(t); | 934 // *ajp++ = low32(t); |
945 // c = high32(t); // c == 0 or 1. | 935 // c = high32(t); // c == 0 or 1. |
946 // } | 936 // } |
947 // return 1; | 937 // return 1; |
948 // } | 938 // } |
949 | 939 |
950 Label done; | 940 Label done; |
951 // R3 = x, no_op if x == 0 | 941 // R3 = x, no_op if x == 0 |
952 __ ldrd(R0, Address(SP, 5 * kWordSize)); // R0 = xi as Smi, R1 = x_digits. | 942 __ ldrd(R0, SP, 5 * kWordSize); // R0 = xi as Smi, R1 = x_digits. |
953 __ add(R1, R1, Operand(R0, LSL, 1)); | 943 __ add(R1, R1, Operand(R0, LSL, 1)); |
954 __ ldr(R3, FieldAddress(R1, TypedData::data_offset())); | 944 __ ldr(R3, FieldAddress(R1, TypedData::data_offset())); |
955 __ tst(R3, Operand(R3)); | 945 __ tst(R3, Operand(R3)); |
956 __ b(&done, EQ); | 946 __ b(&done, EQ); |
957 | 947 |
958 // R6 = SmiUntag(n), no_op if n == 0 | 948 // R6 = SmiUntag(n), no_op if n == 0 |
959 __ ldr(R6, Address(SP, 0 * kWordSize)); | 949 __ ldr(R6, Address(SP, 0 * kWordSize)); |
960 __ Asrs(R6, R6, Operand(kSmiTagSize)); | 950 __ Asrs(R6, R6, Operand(kSmiTagSize)); |
961 __ b(&done, EQ); | 951 __ b(&done, EQ); |
962 | 952 |
963 // R4 = mip = &m_digits[i >> 1] | 953 // R4 = mip = &m_digits[i >> 1] |
964 __ ldrd(R0, Address(SP, 3 * kWordSize)); // R0 = i as Smi, R1 = m_digits. | 954 __ ldrd(R0, SP, 3 * kWordSize); // R0 = i as Smi, R1 = m_digits. |
965 __ add(R1, R1, Operand(R0, LSL, 1)); | 955 __ add(R1, R1, Operand(R0, LSL, 1)); |
966 __ add(R4, R1, Operand(TypedData::data_offset() - kHeapObjectTag)); | 956 __ add(R4, R1, Operand(TypedData::data_offset() - kHeapObjectTag)); |
967 | 957 |
968 // R5 = ajp = &a_digits[j >> 1] | 958 // R5 = ajp = &a_digits[j >> 1] |
969 __ ldrd(R0, Address(SP, 1 * kWordSize)); // R0 = j as Smi, R1 = a_digits. | 959 __ ldrd(R0, SP, 1 * kWordSize); // R0 = j as Smi, R1 = a_digits. |
970 __ add(R1, R1, Operand(R0, LSL, 1)); | 960 __ add(R1, R1, Operand(R0, LSL, 1)); |
971 __ add(R5, R1, Operand(TypedData::data_offset() - kHeapObjectTag)); | 961 __ add(R5, R1, Operand(TypedData::data_offset() - kHeapObjectTag)); |
972 | 962 |
973 // R1 = c = 0 | 963 // R1 = c = 0 |
974 __ mov(R1, Operand(0)); | 964 __ mov(R1, Operand(0)); |
975 | 965 |
976 Label muladd_loop; | 966 Label muladd_loop; |
977 __ Bind(&muladd_loop); | 967 __ Bind(&muladd_loop); |
978 // x: R3 | 968 // x: R3 |
979 // mip: R4 | 969 // mip: R4 |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1045 // c = high64(t); // 33-bit. | 1035 // c = high64(t); // 33-bit. |
1046 // } | 1036 // } |
1047 // uint32_t aj = *ajp; | 1037 // uint32_t aj = *ajp; |
1048 // uint64_t t = aj + c; // 32-bit + 33-bit -> 34-bit. | 1038 // uint64_t t = aj + c; // 32-bit + 33-bit -> 34-bit. |
1049 // *ajp++ = low32(t); | 1039 // *ajp++ = low32(t); |
1050 // *ajp = high32(t); | 1040 // *ajp = high32(t); |
1051 // return 1; | 1041 // return 1; |
1052 // } | 1042 // } |
1053 | 1043 |
1054 // R4 = xip = &x_digits[i >> 1] | 1044 // R4 = xip = &x_digits[i >> 1] |
1055 __ ldrd(R2, Address(SP, 2 * kWordSize)); // R2 = i as Smi, R3 = x_digits | 1045 __ ldrd(R2, SP, 2 * kWordSize); // R2 = i as Smi, R3 = x_digits |
1056 __ add(R3, R3, Operand(R2, LSL, 1)); | 1046 __ add(R3, R3, Operand(R2, LSL, 1)); |
1057 __ add(R4, R3, Operand(TypedData::data_offset() - kHeapObjectTag)); | 1047 __ add(R4, R3, Operand(TypedData::data_offset() - kHeapObjectTag)); |
1058 | 1048 |
1059 // R3 = x = *xip++, return if x == 0 | 1049 // R3 = x = *xip++, return if x == 0 |
1060 Label x_zero; | 1050 Label x_zero; |
1061 __ ldr(R3, Address(R4, Bigint::kBytesPerDigit, Address::PostIndex)); | 1051 __ ldr(R3, Address(R4, Bigint::kBytesPerDigit, Address::PostIndex)); |
1062 __ tst(R3, Operand(R3)); | 1052 __ tst(R3, Operand(R3)); |
1063 __ b(&x_zero, EQ); | 1053 __ b(&x_zero, EQ); |
1064 | 1054 |
1065 // R5 = ajp = &a_digits[i] | 1055 // R5 = ajp = &a_digits[i] |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1123 __ Bind(&done); | 1113 __ Bind(&done); |
1124 // uint32_t aj = *ajp | 1114 // uint32_t aj = *ajp |
1125 __ ldr(R0, Address(R5, 0)); | 1115 __ ldr(R0, Address(R5, 0)); |
1126 | 1116 |
1127 // uint64_t t = aj + c | 1117 // uint64_t t = aj + c |
1128 __ adds(R6, R6, Operand(R0)); | 1118 __ adds(R6, R6, Operand(R0)); |
1129 __ adc(R7, R7, Operand(0)); | 1119 __ adc(R7, R7, Operand(0)); |
1130 | 1120 |
1131 // *ajp = low32(t) = R6 | 1121 // *ajp = low32(t) = R6 |
1132 // *(ajp + 1) = high32(t) = R7 | 1122 // *(ajp + 1) = high32(t) = R7 |
1133 __ strd(R6, Address(R5, 0)); | 1123 __ strd(R6, R5, 0); |
1134 | 1124 |
1135 __ Bind(&x_zero); | 1125 __ Bind(&x_zero); |
1136 __ mov(R0, Operand(Smi::RawValue(1))); // One digit processed. | 1126 __ mov(R0, Operand(Smi::RawValue(1))); // One digit processed. |
1137 __ Ret(); | 1127 __ Ret(); |
1138 } | 1128 } |
1139 | 1129 |
1140 | 1130 |
1141 void Intrinsifier::Bigint_estQuotientDigit(Assembler* assembler) { | 1131 void Intrinsifier::Bigint_estQuotientDigit(Assembler* assembler) { |
1142 // No unsigned 64-bit / 32-bit divide instruction. | 1132 // No unsigned 64-bit / 32-bit divide instruction. |
1143 } | 1133 } |
(...skipping 13 matching lines...) Expand all Loading... |
1157 // } | 1147 // } |
1158 | 1148 |
1159 // R4 = args | 1149 // R4 = args |
1160 __ ldr(R4, Address(SP, 2 * kWordSize)); // args | 1150 __ ldr(R4, Address(SP, 2 * kWordSize)); // args |
1161 | 1151 |
1162 // R3 = rho = args[2] | 1152 // R3 = rho = args[2] |
1163 __ ldr(R3, FieldAddress(R4, | 1153 __ ldr(R3, FieldAddress(R4, |
1164 TypedData::data_offset() + 2*Bigint::kBytesPerDigit)); | 1154 TypedData::data_offset() + 2*Bigint::kBytesPerDigit)); |
1165 | 1155 |
1166 // R2 = digits[i >> 1] | 1156 // R2 = digits[i >> 1] |
1167 __ ldrd(R0, Address(SP, 0 * kWordSize)); // R0 = i as Smi, R1 = digits | 1157 __ ldrd(R0, SP, 0 * kWordSize); // R0 = i as Smi, R1 = digits |
1168 __ add(R1, R1, Operand(R0, LSL, 1)); | 1158 __ add(R1, R1, Operand(R0, LSL, 1)); |
1169 __ ldr(R2, FieldAddress(R1, TypedData::data_offset())); | 1159 __ ldr(R2, FieldAddress(R1, TypedData::data_offset())); |
1170 | 1160 |
1171 // R1:R0 = t = rho*d | 1161 // R1:R0 = t = rho*d |
1172 __ umull(R0, R1, R2, R3); | 1162 __ umull(R0, R1, R2, R3); |
1173 | 1163 |
1174 // args[4] = t mod DIGIT_BASE = low32(t) | 1164 // args[4] = t mod DIGIT_BASE = low32(t) |
1175 __ str(R0, | 1165 __ str(R0, |
1176 FieldAddress(R4, TypedData::data_offset() + 4*Bigint::kBytesPerDigit)); | 1166 FieldAddress(R4, TypedData::data_offset() + 4*Bigint::kBytesPerDigit)); |
1177 | 1167 |
(...skipping 776 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1954 Isolate* isolate = Isolate::Current(); | 1944 Isolate* isolate = Isolate::Current(); |
1955 __ LoadImmediate(R1, reinterpret_cast<uword>(isolate)); | 1945 __ LoadImmediate(R1, reinterpret_cast<uword>(isolate)); |
1956 // Set return value to Isolate::current_tag_. | 1946 // Set return value to Isolate::current_tag_. |
1957 __ ldr(R0, Address(R1, Isolate::current_tag_offset())); | 1947 __ ldr(R0, Address(R1, Isolate::current_tag_offset())); |
1958 __ Ret(); | 1948 __ Ret(); |
1959 } | 1949 } |
1960 | 1950 |
1961 } // namespace dart | 1951 } // namespace dart |
1962 | 1952 |
1963 #endif // defined TARGET_ARCH_ARM | 1953 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |