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