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