| 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 |