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 907 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
918 | 918 |
919 // R7 = &digits[a_used >> 1], a_used is Smi. | 919 // R7 = &digits[a_used >> 1], a_used is Smi. |
920 __ add(R7, R3, Operand(R4, LSL, 1)); | 920 __ add(R7, R3, Operand(R4, LSL, 1)); |
921 | 921 |
922 // R8 = &digits[used >> 1], used is Smi. | 922 // R8 = &digits[used >> 1], used is Smi. |
923 __ add(R8, R3, Operand(R2, LSL, 1)); | 923 __ add(R8, R3, Operand(R2, LSL, 1)); |
924 | 924 |
925 __ adds(R0, R0, Operand(0)); // carry flag = 0 | 925 __ adds(R0, R0, Operand(0)); // carry flag = 0 |
926 Label add_loop; | 926 Label add_loop; |
927 __ Bind(&add_loop); | 927 __ Bind(&add_loop); |
928 __ ldr(R0, Address(R3, kWordSize, Address::PostIndex)); | 928 __ ldr(R0, Address(R3, Bigint::kBytesPerDigit, Address::PostIndex)); |
929 __ ldr(R1, Address(R5, kWordSize, Address::PostIndex)); | 929 __ ldr(R1, Address(R5, Bigint::kBytesPerDigit, Address::PostIndex)); |
930 __ adcs(R0, R0, Operand(R1)); | 930 __ adcs(R0, R0, Operand(R1)); |
931 __ teq(R3, Operand(R7)); // Does not affect carry flag. | 931 __ teq(R3, Operand(R7)); // Does not affect carry flag. |
932 __ str(R0, Address(R6, kWordSize, Address::PostIndex)); | 932 __ str(R0, Address(R6, Bigint::kBytesPerDigit, Address::PostIndex)); |
933 __ b(&add_loop, NE); | 933 __ b(&add_loop, NE); |
934 | 934 |
935 Label last_carry; | 935 Label last_carry; |
936 __ teq(R3, Operand(R8)); // Does not affect carry flag. | 936 __ teq(R3, Operand(R8)); // Does not affect carry flag. |
937 __ b(&last_carry, EQ); | 937 __ b(&last_carry, EQ); |
938 | 938 |
939 Label carry_loop; | 939 Label carry_loop; |
940 __ Bind(&carry_loop); | 940 __ Bind(&carry_loop); |
941 __ ldr(R0, Address(R3, kWordSize, Address::PostIndex)); | 941 __ ldr(R0, Address(R3, Bigint::kBytesPerDigit, Address::PostIndex)); |
942 __ adcs(R0, R0, Operand(0)); | 942 __ adcs(R0, R0, Operand(0)); |
943 __ teq(R3, Operand(R8)); // Does not affect carry flag. | 943 __ teq(R3, Operand(R8)); // Does not affect carry flag. |
944 __ str(R0, Address(R6, kWordSize, Address::PostIndex)); | 944 __ str(R0, Address(R6, Bigint::kBytesPerDigit, Address::PostIndex)); |
945 __ b(&carry_loop, NE); | 945 __ b(&carry_loop, NE); |
946 | 946 |
947 __ Bind(&last_carry); | 947 __ Bind(&last_carry); |
948 __ mov(R0, Operand(0)); | 948 __ mov(R0, Operand(0)); |
949 __ adc(R0, R0, Operand(0)); | 949 __ adc(R0, R0, Operand(0)); |
950 __ str(R0, Address(R6, 0)); | 950 __ str(R0, Address(R6, 0)); |
951 | 951 |
952 // Returning Object::null() is not required, since this method is private. | 952 // Returning Object::null() is not required, since this method is private. |
953 __ Ret(); | 953 __ Ret(); |
954 } | 954 } |
(...skipping 18 matching lines...) Expand all Loading... |
973 | 973 |
974 // R7 = &digits[a_used >> 1], a_used is Smi. | 974 // R7 = &digits[a_used >> 1], a_used is Smi. |
975 __ add(R7, R3, Operand(R4, LSL, 1)); | 975 __ add(R7, R3, Operand(R4, LSL, 1)); |
976 | 976 |
977 // R8 = &digits[used >> 1], used is Smi. | 977 // R8 = &digits[used >> 1], used is Smi. |
978 __ add(R8, R3, Operand(R2, LSL, 1)); | 978 __ add(R8, R3, Operand(R2, LSL, 1)); |
979 | 979 |
980 __ subs(R0, R0, Operand(0)); // carry flag = 1 | 980 __ subs(R0, R0, Operand(0)); // carry flag = 1 |
981 Label sub_loop; | 981 Label sub_loop; |
982 __ Bind(&sub_loop); | 982 __ Bind(&sub_loop); |
983 __ ldr(R0, Address(R3, kWordSize, Address::PostIndex)); | 983 __ ldr(R0, Address(R3, Bigint::kBytesPerDigit, Address::PostIndex)); |
984 __ ldr(R1, Address(R5, kWordSize, Address::PostIndex)); | 984 __ ldr(R1, Address(R5, Bigint::kBytesPerDigit, Address::PostIndex)); |
985 __ sbcs(R0, R0, Operand(R1)); | 985 __ sbcs(R0, R0, Operand(R1)); |
986 __ teq(R3, Operand(R7)); // Does not affect carry flag. | 986 __ teq(R3, Operand(R7)); // Does not affect carry flag. |
987 __ str(R0, Address(R6, kWordSize, Address::PostIndex)); | 987 __ str(R0, Address(R6, Bigint::kBytesPerDigit, Address::PostIndex)); |
988 __ b(&sub_loop, NE); | 988 __ b(&sub_loop, NE); |
989 | 989 |
990 Label done; | 990 Label done; |
991 __ teq(R3, Operand(R8)); // Does not affect carry flag. | 991 __ teq(R3, Operand(R8)); // Does not affect carry flag. |
992 __ b(&done, EQ); | 992 __ b(&done, EQ); |
993 | 993 |
994 Label carry_loop; | 994 Label carry_loop; |
995 __ Bind(&carry_loop); | 995 __ Bind(&carry_loop); |
996 __ ldr(R0, Address(R3, kWordSize, Address::PostIndex)); | 996 __ ldr(R0, Address(R3, Bigint::kBytesPerDigit, Address::PostIndex)); |
997 __ sbcs(R0, R0, Operand(0)); | 997 __ sbcs(R0, R0, Operand(0)); |
998 __ teq(R3, Operand(R8)); // Does not affect carry flag. | 998 __ teq(R3, Operand(R8)); // Does not affect carry flag. |
999 __ str(R0, Address(R6, kWordSize, Address::PostIndex)); | 999 __ str(R0, Address(R6, Bigint::kBytesPerDigit, Address::PostIndex)); |
1000 __ b(&carry_loop, NE); | 1000 __ b(&carry_loop, NE); |
1001 | 1001 |
1002 __ Bind(&done); | 1002 __ Bind(&done); |
1003 // Returning Object::null() is not required, since this method is private. | 1003 // Returning Object::null() is not required, since this method is private. |
1004 __ Ret(); | 1004 __ Ret(); |
1005 } | 1005 } |
1006 | 1006 |
1007 | 1007 |
1008 void Intrinsifier::Bigint_mulAdd(Assembler* assembler) { | 1008 void Intrinsifier::Bigint_mulAdd(Assembler* assembler) { |
1009 if (TargetCPUFeatures::arm_version() != ARMv7) { | 1009 if (TargetCPUFeatures::arm_version() != ARMv7) { |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1063 | 1063 |
1064 Label muladd_loop; | 1064 Label muladd_loop; |
1065 __ Bind(&muladd_loop); | 1065 __ Bind(&muladd_loop); |
1066 // x: R3 | 1066 // x: R3 |
1067 // mip: R4 | 1067 // mip: R4 |
1068 // ajp: R5 | 1068 // ajp: R5 |
1069 // c: R1 | 1069 // c: R1 |
1070 // n: R6 | 1070 // n: R6 |
1071 | 1071 |
1072 // uint32_t mi = *mip++ | 1072 // uint32_t mi = *mip++ |
1073 __ ldr(R2, Address(R4, kWordSize, Address::PostIndex)); | 1073 __ ldr(R2, Address(R4, Bigint::kBytesPerDigit, Address::PostIndex)); |
1074 | 1074 |
1075 // uint32_t aj = *ajp | 1075 // uint32_t aj = *ajp |
1076 __ ldr(R0, Address(R5, 0)); | 1076 __ ldr(R0, Address(R5, 0)); |
1077 | 1077 |
1078 // uint64_t t = x*mi + aj + c | 1078 // uint64_t t = x*mi + aj + c |
1079 __ umaal(R0, R1, R2, R3); // R1:R0 = R2*R3 + R1 + R0. | 1079 __ umaal(R0, R1, R2, R3); // R1:R0 = R2*R3 + R1 + R0. |
1080 | 1080 |
1081 // *ajp++ = low32(t) = R0 | 1081 // *ajp++ = low32(t) = R0 |
1082 __ str(R0, Address(R5, kWordSize, Address::PostIndex)); | 1082 __ str(R0, Address(R5, Bigint::kBytesPerDigit, Address::PostIndex)); |
1083 | 1083 |
1084 // c = high32(t) = R1 | 1084 // c = high32(t) = R1 |
1085 | 1085 |
1086 // while (--n > 0) | 1086 // while (--n > 0) |
1087 __ subs(R6, R6, Operand(1)); // --n | 1087 __ subs(R6, R6, Operand(1)); // --n |
1088 __ b(&muladd_loop, NE); | 1088 __ b(&muladd_loop, NE); |
1089 | 1089 |
1090 __ tst(R1, Operand(R1)); | 1090 __ tst(R1, Operand(R1)); |
1091 __ b(&done, EQ); | 1091 __ b(&done, EQ); |
1092 | 1092 |
1093 // *ajp++ += c | 1093 // *ajp++ += c |
1094 __ ldr(R0, Address(R5, 0)); | 1094 __ ldr(R0, Address(R5, 0)); |
1095 __ adds(R0, R0, Operand(R1)); | 1095 __ adds(R0, R0, Operand(R1)); |
1096 __ str(R0, Address(R5, kWordSize, Address::PostIndex)); | 1096 __ str(R0, Address(R5, Bigint::kBytesPerDigit, Address::PostIndex)); |
1097 __ b(&done, CC); | 1097 __ b(&done, CC); |
1098 | 1098 |
1099 Label propagate_carry_loop; | 1099 Label propagate_carry_loop; |
1100 __ Bind(&propagate_carry_loop); | 1100 __ Bind(&propagate_carry_loop); |
1101 __ ldr(R0, Address(R5, 0)); | 1101 __ ldr(R0, Address(R5, 0)); |
1102 __ adds(R0, R0, Operand(1)); | 1102 __ adds(R0, R0, Operand(1)); |
1103 __ str(R0, Address(R5, kWordSize, Address::PostIndex)); | 1103 __ str(R0, Address(R5, Bigint::kBytesPerDigit, Address::PostIndex)); |
1104 __ b(&propagate_carry_loop, CS); | 1104 __ b(&propagate_carry_loop, CS); |
1105 | 1105 |
1106 __ Bind(&done); | 1106 __ Bind(&done); |
1107 // Returning Object::null() is not required, since this method is private. | 1107 // Returning Object::null() is not required, since this method is private. |
1108 __ Ret(); | 1108 __ Ret(); |
1109 } | 1109 } |
1110 | 1110 |
1111 | 1111 |
1112 void Intrinsifier::Bigint_sqrAdd(Assembler* assembler) { | 1112 void Intrinsifier::Bigint_sqrAdd(Assembler* assembler) { |
1113 if (TargetCPUFeatures::arm_version() != ARMv7) { | 1113 if (TargetCPUFeatures::arm_version() != ARMv7) { |
(...skipping 24 matching lines...) Expand all Loading... |
1138 // *ajp = high32(t); | 1138 // *ajp = high32(t); |
1139 // } | 1139 // } |
1140 | 1140 |
1141 // R4 = xip = &x_digits[i >> 1] | 1141 // R4 = xip = &x_digits[i >> 1] |
1142 __ ldrd(R2, Address(SP, 2 * kWordSize)); // R2 = i as Smi, R3 = x_digits | 1142 __ ldrd(R2, Address(SP, 2 * kWordSize)); // R2 = i as Smi, R3 = x_digits |
1143 __ add(R3, R3, Operand(R2, LSL, 1)); | 1143 __ add(R3, R3, Operand(R2, LSL, 1)); |
1144 __ add(R4, R3, Operand(TypedData::data_offset() - kHeapObjectTag)); | 1144 __ add(R4, R3, Operand(TypedData::data_offset() - kHeapObjectTag)); |
1145 | 1145 |
1146 // R3 = x = *xip++, return if x == 0 | 1146 // R3 = x = *xip++, return if x == 0 |
1147 Label x_zero; | 1147 Label x_zero; |
1148 __ ldr(R3, Address(R4, kWordSize, Address::PostIndex)); | 1148 __ ldr(R3, Address(R4, Bigint::kBytesPerDigit, Address::PostIndex)); |
1149 __ tst(R3, Operand(R3)); | 1149 __ tst(R3, Operand(R3)); |
1150 __ b(&x_zero, EQ); | 1150 __ b(&x_zero, EQ); |
1151 | 1151 |
1152 // R5 = ajp = &a_digits[i] | 1152 // R5 = ajp = &a_digits[i] |
1153 __ ldr(R1, Address(SP, 1 * kWordSize)); // a_digits | 1153 __ ldr(R1, Address(SP, 1 * kWordSize)); // a_digits |
1154 __ add(R1, R1, Operand(R2, LSL, 2)); // j == 2*i, i is Smi. | 1154 __ add(R1, R1, Operand(R2, LSL, 2)); // j == 2*i, i is Smi. |
1155 __ add(R5, R1, Operand(TypedData::data_offset() - kHeapObjectTag)); | 1155 __ add(R5, R1, Operand(TypedData::data_offset() - kHeapObjectTag)); |
1156 | 1156 |
1157 // R6:R0 = t = x*x + *ajp | 1157 // R6:R0 = t = x*x + *ajp |
1158 __ ldr(R0, Address(R5, 0)); | 1158 __ ldr(R0, Address(R5, 0)); |
1159 __ mov(R6, Operand(0)); | 1159 __ mov(R6, Operand(0)); |
1160 __ umaal(R0, R6, R3, R3); // R6:R0 = R3*R3 + R6 + R0. | 1160 __ umaal(R0, R6, R3, R3); // R6:R0 = R3*R3 + R6 + R0. |
1161 | 1161 |
1162 // *ajp++ = low32(t) = R0 | 1162 // *ajp++ = low32(t) = R0 |
1163 __ str(R0, Address(R5, kWordSize, Address::PostIndex)); | 1163 __ str(R0, Address(R5, Bigint::kBytesPerDigit, Address::PostIndex)); |
1164 | 1164 |
1165 // R6 = low32(c) = high32(t) | 1165 // R6 = low32(c) = high32(t) |
1166 // R7 = high32(c) = 0 | 1166 // R7 = high32(c) = 0 |
1167 __ mov(R7, Operand(0)); | 1167 __ mov(R7, Operand(0)); |
1168 | 1168 |
1169 // int n = used - i - 1 | 1169 // int n = used - i - 1 |
1170 __ ldr(R0, Address(SP, 0 * kWordSize)); // used is Smi | 1170 __ ldr(R0, Address(SP, 0 * kWordSize)); // used is Smi |
1171 __ sub(R8, R0, Operand(R2)); | 1171 __ sub(R8, R0, Operand(R2)); |
1172 __ mov(R0, Operand(2)); // while (--n >= 0) | 1172 __ mov(R0, Operand(2)); // while (--n >= 0) |
1173 __ rsbs(R8, R0, Operand(R8, ASR, kSmiTagSize)); | 1173 __ rsbs(R8, R0, Operand(R8, ASR, kSmiTagSize)); |
1174 | 1174 |
1175 Label loop, done; | 1175 Label loop, done; |
1176 __ b(&done, MI); | 1176 __ b(&done, MI); |
1177 | 1177 |
1178 __ Bind(&loop); | 1178 __ Bind(&loop); |
1179 // x: R3 | 1179 // x: R3 |
1180 // xip: R4 | 1180 // xip: R4 |
1181 // ajp: R5 | 1181 // ajp: R5 |
1182 // c: R7:R6 | 1182 // c: R7:R6 |
1183 // t: R2:R1:R0 (not live at loop entry) | 1183 // t: R2:R1:R0 (not live at loop entry) |
1184 // n: R8 | 1184 // n: R8 |
1185 | 1185 |
1186 // uint32_t xi = *xip++ | 1186 // uint32_t xi = *xip++ |
1187 __ ldr(R2, Address(R4, kWordSize, Address::PostIndex)); | 1187 __ ldr(R2, Address(R4, Bigint::kBytesPerDigit, Address::PostIndex)); |
1188 | 1188 |
1189 // uint32_t aj = *ajp | 1189 // uint32_t aj = *ajp |
1190 __ ldr(R1, Address(R5, 0)); | 1190 __ ldr(R1, Address(R5, 0)); |
1191 | 1191 |
1192 // uint96_t t = R2:R1:R0 = 2*x*xi + aj + c | 1192 // uint96_t t = R2:R1:R0 = 2*x*xi + aj + c |
1193 __ mov(R0, Operand(0)); | 1193 __ mov(R0, Operand(0)); |
1194 __ umaal(R0, R1, R2, R3); // R1:R0 = R3*R2 + R1 + R0 = x*xi + aj + 0. | 1194 __ umaal(R0, R1, R2, R3); // R1:R0 = R3*R2 + R1 + R0 = x*xi + aj + 0. |
1195 __ umlal(R6, R7, R2, R3); // R7:R6 += R3*R2; c += x*xi. | 1195 __ umlal(R6, R7, R2, R3); // R7:R6 += R3*R2; c += x*xi. |
1196 __ adds(R0, R0, Operand(R6)); | 1196 __ adds(R0, R0, Operand(R6)); |
1197 __ adcs(R6, R1, Operand(R7)); | 1197 __ adcs(R6, R1, Operand(R7)); |
1198 __ mov(R7, Operand(0)); | 1198 __ mov(R7, Operand(0)); |
1199 __ adc(R7, R7, Operand(0)); // R7:R6:R0 = R1:R0 + R7:R6 = 2*x*xi + aj + c. | 1199 __ adc(R7, R7, Operand(0)); // R7:R6:R0 = R1:R0 + R7:R6 = 2*x*xi + aj + c. |
1200 | 1200 |
1201 // *ajp++ = low32(t) = R0 | 1201 // *ajp++ = low32(t) = R0 |
1202 __ str(R0, Address(R5, kWordSize, Address::PostIndex)); | 1202 __ str(R0, Address(R5, Bigint::kBytesPerDigit, Address::PostIndex)); |
1203 | 1203 |
1204 // while (--n >= 0) | 1204 // while (--n >= 0) |
1205 __ subs(R8, R8, Operand(1)); // --n | 1205 __ subs(R8, R8, Operand(1)); // --n |
1206 __ b(&loop, PL); | 1206 __ b(&loop, PL); |
1207 | 1207 |
1208 __ Bind(&done); | 1208 __ Bind(&done); |
1209 // uint32_t aj = *ajp | 1209 // uint32_t aj = *ajp |
1210 __ ldr(R0, Address(R5, 0)); | 1210 __ ldr(R0, Address(R5, 0)); |
1211 | 1211 |
1212 // uint64_t t = aj + c | 1212 // uint64_t t = aj + c |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1248 | 1248 |
1249 // R2 = digits[i >> 1] | 1249 // R2 = digits[i >> 1] |
1250 __ ldrd(R0, Address(SP, 0 * kWordSize)); // R0 = i as Smi, R1 = digits | 1250 __ ldrd(R0, Address(SP, 0 * kWordSize)); // R0 = i as Smi, R1 = digits |
1251 __ add(R1, R1, Operand(R0, LSL, 1)); | 1251 __ add(R1, R1, Operand(R0, LSL, 1)); |
1252 __ ldr(R2, FieldAddress(R1, TypedData::data_offset())); | 1252 __ ldr(R2, FieldAddress(R1, TypedData::data_offset())); |
1253 | 1253 |
1254 // R1:R0 = t = rho*d | 1254 // R1:R0 = t = rho*d |
1255 __ umull(R0, R1, R2, R3); | 1255 __ umull(R0, R1, R2, R3); |
1256 | 1256 |
1257 // args[1] = t mod DIGIT_BASE = low32(t) | 1257 // args[1] = t mod DIGIT_BASE = low32(t) |
1258 __ str(R0, FieldAddress(R4, TypedData::data_offset() + kWordSize)); | 1258 __ str(R0, |
| 1259 FieldAddress(R4, TypedData::data_offset() + Bigint::kBytesPerDigit)); |
1259 | 1260 |
1260 // Returning Object::null() is not required, since this method is private. | 1261 // Returning Object::null() is not required, since this method is private. |
1261 __ Ret(); | 1262 __ Ret(); |
1262 } | 1263 } |
1263 | 1264 |
1264 | 1265 |
1265 // Check if the last argument is a double, jump to label 'is_smi' if smi | 1266 // Check if the last argument is a double, jump to label 'is_smi' if smi |
1266 // (easy to convert to double), otherwise jump to label 'not_double_smi', | 1267 // (easy to convert to double), otherwise jump to label 'not_double_smi', |
1267 // Returns the last argument in R0. | 1268 // Returns the last argument in R0. |
1268 static void TestLastArgumentIsDouble(Assembler* assembler, | 1269 static void TestLastArgumentIsDouble(Assembler* assembler, |
(...skipping 730 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1999 Isolate* isolate = Isolate::Current(); | 2000 Isolate* isolate = Isolate::Current(); |
2000 __ LoadImmediate(R1, reinterpret_cast<uword>(isolate)); | 2001 __ LoadImmediate(R1, reinterpret_cast<uword>(isolate)); |
2001 // Set return value to Isolate::current_tag_. | 2002 // Set return value to Isolate::current_tag_. |
2002 __ ldr(R0, Address(R1, Isolate::current_tag_offset())); | 2003 __ ldr(R0, Address(R1, Isolate::current_tag_offset())); |
2003 __ Ret(); | 2004 __ Ret(); |
2004 } | 2005 } |
2005 | 2006 |
2006 } // namespace dart | 2007 } // namespace dart |
2007 | 2008 |
2008 #endif // defined TARGET_ARCH_ARM | 2009 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |