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 899 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
910 __ str(R0, Address(R6, Bigint::kBytesPerDigit, Address::PostIndex)); | 910 __ str(R0, Address(R6, Bigint::kBytesPerDigit, Address::PostIndex)); |
911 __ b(&carry_loop, NE); | 911 __ b(&carry_loop, NE); |
912 | 912 |
913 __ Bind(&done); | 913 __ Bind(&done); |
914 // Returning Object::null() is not required, since this method is private. | 914 // Returning Object::null() is not required, since this method is private. |
915 __ Ret(); | 915 __ Ret(); |
916 } | 916 } |
917 | 917 |
918 | 918 |
919 void Intrinsifier::Bigint_mulAdd(Assembler* assembler) { | 919 void Intrinsifier::Bigint_mulAdd(Assembler* assembler) { |
920 if (TargetCPUFeatures::arm_version() != ARMv7) { | |
921 return; | |
922 } | |
923 // Pseudo code: | 920 // Pseudo code: |
924 // static int _mulAdd(Uint32List x_digits, int xi, | 921 // static int _mulAdd(Uint32List x_digits, int xi, |
925 // Uint32List m_digits, int i, | 922 // Uint32List m_digits, int i, |
926 // Uint32List a_digits, int j, int n) { | 923 // Uint32List a_digits, int j, int n) { |
927 // uint32_t x = x_digits[xi >> 1]; // xi is Smi. | 924 // uint32_t x = x_digits[xi >> 1]; // xi is Smi. |
928 // if (x == 0 || n == 0) { | 925 // if (x == 0 || n == 0) { |
929 // return 1; | 926 // return 1; |
930 // } | 927 // } |
931 // uint32_t* mip = &m_digits[i >> 1]; // i is Smi. | 928 // uint32_t* mip = &m_digits[i >> 1]; // i is Smi. |
932 // uint32_t* ajp = &a_digits[j >> 1]; // j is Smi. | 929 // uint32_t* ajp = &a_digits[j >> 1]; // j is Smi. |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1015 __ str(R0, Address(R5, Bigint::kBytesPerDigit, Address::PostIndex)); | 1012 __ str(R0, Address(R5, Bigint::kBytesPerDigit, Address::PostIndex)); |
1016 __ b(&propagate_carry_loop, CS); | 1013 __ b(&propagate_carry_loop, CS); |
1017 | 1014 |
1018 __ Bind(&done); | 1015 __ Bind(&done); |
1019 __ mov(R0, Operand(Smi::RawValue(1))); // One digit processed. | 1016 __ mov(R0, Operand(Smi::RawValue(1))); // One digit processed. |
1020 __ Ret(); | 1017 __ Ret(); |
1021 } | 1018 } |
1022 | 1019 |
1023 | 1020 |
1024 void Intrinsifier::Bigint_sqrAdd(Assembler* assembler) { | 1021 void Intrinsifier::Bigint_sqrAdd(Assembler* assembler) { |
1025 if (TargetCPUFeatures::arm_version() != ARMv7) { | |
1026 return; | |
1027 } | |
1028 // Pseudo code: | 1022 // Pseudo code: |
1029 // static int _sqrAdd(Uint32List x_digits, int i, | 1023 // static int _sqrAdd(Uint32List x_digits, int i, |
1030 // Uint32List a_digits, int used) { | 1024 // Uint32List a_digits, int used) { |
1031 // uint32_t* xip = &x_digits[i >> 1]; // i is Smi. | 1025 // uint32_t* xip = &x_digits[i >> 1]; // i is Smi. |
1032 // uint32_t x = *xip++; | 1026 // uint32_t x = *xip++; |
1033 // if (x == 0) return 1; | 1027 // if (x == 0) return 1; |
1034 // uint32_t* ajp = &a_digits[i]; // j == 2*i, i is Smi. | 1028 // uint32_t* ajp = &a_digits[i]; // j == 2*i, i is Smi. |
1035 // uint32_t aj = *ajp; | 1029 // uint32_t aj = *ajp; |
1036 // uint64_t t = x*x + aj; | 1030 // uint64_t t = x*x + aj; |
1037 // *ajp++ = low32(t); | 1031 // *ajp++ = low32(t); |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1137 __ Ret(); | 1131 __ Ret(); |
1138 } | 1132 } |
1139 | 1133 |
1140 | 1134 |
1141 void Intrinsifier::Bigint_estQuotientDigit(Assembler* assembler) { | 1135 void Intrinsifier::Bigint_estQuotientDigit(Assembler* assembler) { |
1142 // No unsigned 64-bit / 32-bit divide instruction. | 1136 // No unsigned 64-bit / 32-bit divide instruction. |
1143 } | 1137 } |
1144 | 1138 |
1145 | 1139 |
1146 void Intrinsifier::Montgomery_mulMod(Assembler* assembler) { | 1140 void Intrinsifier::Montgomery_mulMod(Assembler* assembler) { |
1147 if (TargetCPUFeatures::arm_version() != ARMv7) { | |
1148 return; | |
1149 } | |
1150 // Pseudo code: | 1141 // Pseudo code: |
1151 // static int _mulMod(Uint32List args, Uint32List digits, int i) { | 1142 // static int _mulMod(Uint32List args, Uint32List digits, int i) { |
1152 // uint32_t rho = args[_RHO]; // _RHO == 2. | 1143 // uint32_t rho = args[_RHO]; // _RHO == 2. |
1153 // uint32_t d = digits[i >> 1]; // i is Smi. | 1144 // uint32_t d = digits[i >> 1]; // i is Smi. |
1154 // uint64_t t = rho*d; | 1145 // uint64_t t = rho*d; |
1155 // args[_MU] = t mod DIGIT_BASE; // _MU == 4. | 1146 // args[_MU] = t mod DIGIT_BASE; // _MU == 4. |
1156 // return 1; | 1147 // return 1; |
1157 // } | 1148 // } |
1158 | 1149 |
1159 // R4 = args | 1150 // R4 = args |
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1437 __ b(&double_op); | 1428 __ b(&double_op); |
1438 __ Bind(&fall_through); | 1429 __ Bind(&fall_through); |
1439 } | 1430 } |
1440 } | 1431 } |
1441 | 1432 |
1442 | 1433 |
1443 // var state = ((_A * (_state[kSTATE_LO])) + _state[kSTATE_HI]) & _MASK_64; | 1434 // var state = ((_A * (_state[kSTATE_LO])) + _state[kSTATE_HI]) & _MASK_64; |
1444 // _state[kSTATE_LO] = state & _MASK_32; | 1435 // _state[kSTATE_LO] = state & _MASK_32; |
1445 // _state[kSTATE_HI] = state >> 32; | 1436 // _state[kSTATE_HI] = state >> 32; |
1446 void Intrinsifier::Random_nextState(Assembler* assembler) { | 1437 void Intrinsifier::Random_nextState(Assembler* assembler) { |
1447 // No 32x32 -> 64 bit multiply/accumulate on ARMv5 or ARMv6. | 1438 const Library& math_lib = Library::Handle(Library::MathLibrary()); |
1448 if (TargetCPUFeatures::arm_version() == ARMv7) { | 1439 ASSERT(!math_lib.IsNull()); |
1449 const Library& math_lib = Library::Handle(Library::MathLibrary()); | 1440 const Class& random_class = Class::Handle( |
1450 ASSERT(!math_lib.IsNull()); | 1441 math_lib.LookupClassAllowPrivate(Symbols::_Random())); |
1451 const Class& random_class = Class::Handle( | 1442 ASSERT(!random_class.IsNull()); |
1452 math_lib.LookupClassAllowPrivate(Symbols::_Random())); | 1443 const Field& state_field = Field::ZoneHandle( |
1453 ASSERT(!random_class.IsNull()); | 1444 random_class.LookupInstanceField(Symbols::_state())); |
1454 const Field& state_field = Field::ZoneHandle( | 1445 ASSERT(!state_field.IsNull()); |
1455 random_class.LookupInstanceField(Symbols::_state())); | 1446 const Field& random_A_field = Field::ZoneHandle( |
1456 ASSERT(!state_field.IsNull()); | 1447 random_class.LookupStaticField(Symbols::_A())); |
1457 const Field& random_A_field = Field::ZoneHandle( | 1448 ASSERT(!random_A_field.IsNull()); |
1458 random_class.LookupStaticField(Symbols::_A())); | 1449 ASSERT(random_A_field.is_const()); |
1459 ASSERT(!random_A_field.IsNull()); | 1450 const Instance& a_value = Instance::Handle(random_A_field.value()); |
1460 ASSERT(random_A_field.is_const()); | 1451 const int64_t a_int_value = Integer::Cast(a_value).AsInt64Value(); |
1461 const Instance& a_value = Instance::Handle(random_A_field.value()); | 1452 // 'a_int_value' is a mask. |
1462 const int64_t a_int_value = Integer::Cast(a_value).AsInt64Value(); | 1453 ASSERT(Utils::IsUint(32, a_int_value)); |
1463 // 'a_int_value' is a mask. | 1454 int32_t a_int32_value = static_cast<int32_t>(a_int_value); |
1464 ASSERT(Utils::IsUint(32, a_int_value)); | |
1465 int32_t a_int32_value = static_cast<int32_t>(a_int_value); | |
1466 | 1455 |
1467 __ ldr(R0, Address(SP, 0 * kWordSize)); // Receiver. | 1456 __ ldr(R0, Address(SP, 0 * kWordSize)); // Receiver. |
1468 __ ldr(R1, FieldAddress(R0, state_field.Offset())); // Field '_state'. | 1457 __ ldr(R1, FieldAddress(R0, state_field.Offset())); // Field '_state'. |
1469 // Addresses of _state[0] and _state[1]. | 1458 // Addresses of _state[0] and _state[1]. |
1470 | 1459 |
1471 const int64_t disp_0 = Instance::DataOffsetFor(kTypedDataUint32ArrayCid); | 1460 const int64_t disp_0 = Instance::DataOffsetFor(kTypedDataUint32ArrayCid); |
1472 const int64_t disp_1 = disp_0 + | 1461 const int64_t disp_1 = disp_0 + |
1473 Instance::ElementSizeFor(kTypedDataUint32ArrayCid); | 1462 Instance::ElementSizeFor(kTypedDataUint32ArrayCid); |
1474 | 1463 |
1475 __ LoadImmediate(R0, a_int32_value); | 1464 __ LoadImmediate(R0, a_int32_value); |
1476 __ LoadFromOffset(kWord, R2, R1, disp_0 - kHeapObjectTag); | 1465 __ LoadFromOffset(kWord, R2, R1, disp_0 - kHeapObjectTag); |
1477 __ LoadFromOffset(kWord, R3, R1, disp_1 - kHeapObjectTag); | 1466 __ LoadFromOffset(kWord, R3, R1, disp_1 - kHeapObjectTag); |
1478 __ mov(R6, Operand(0)); // Zero extend unsigned _state[kSTATE_HI]. | 1467 __ mov(R6, Operand(0)); // Zero extend unsigned _state[kSTATE_HI]. |
1479 // Unsigned 32-bit multiply and 64-bit accumulate into R6:R3. | 1468 // Unsigned 32-bit multiply and 64-bit accumulate into R6:R3. |
1480 __ umlal(R3, R6, R0, R2); // R6:R3 <- R6:R3 + R0 * R2. | 1469 __ umlal(R3, R6, R0, R2); // R6:R3 <- R6:R3 + R0 * R2. |
1481 __ StoreToOffset(kWord, R3, R1, disp_0 - kHeapObjectTag); | 1470 __ StoreToOffset(kWord, R3, R1, disp_0 - kHeapObjectTag); |
1482 __ StoreToOffset(kWord, R6, R1, disp_1 - kHeapObjectTag); | 1471 __ StoreToOffset(kWord, R6, R1, disp_1 - kHeapObjectTag); |
1483 __ Ret(); | 1472 __ Ret(); |
1484 } | |
1485 } | 1473 } |
1486 | 1474 |
1487 | 1475 |
1488 void Intrinsifier::ObjectEquals(Assembler* assembler) { | 1476 void Intrinsifier::ObjectEquals(Assembler* assembler) { |
1489 __ ldr(R0, Address(SP, 0 * kWordSize)); | 1477 __ ldr(R0, Address(SP, 0 * kWordSize)); |
1490 __ ldr(R1, Address(SP, 1 * kWordSize)); | 1478 __ ldr(R1, Address(SP, 1 * kWordSize)); |
1491 __ cmp(R0, Operand(R1)); | 1479 __ cmp(R0, Operand(R1)); |
1492 __ LoadObject(R0, Bool::False(), NE); | 1480 __ LoadObject(R0, Bool::False(), NE); |
1493 __ LoadObject(R0, Bool::True(), EQ); | 1481 __ LoadObject(R0, Bool::True(), EQ); |
1494 __ Ret(); | 1482 __ Ret(); |
(...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1954 Isolate* isolate = Isolate::Current(); | 1942 Isolate* isolate = Isolate::Current(); |
1955 __ LoadImmediate(R1, reinterpret_cast<uword>(isolate)); | 1943 __ LoadImmediate(R1, reinterpret_cast<uword>(isolate)); |
1956 // Set return value to Isolate::current_tag_. | 1944 // Set return value to Isolate::current_tag_. |
1957 __ ldr(R0, Address(R1, Isolate::current_tag_offset())); | 1945 __ ldr(R0, Address(R1, Isolate::current_tag_offset())); |
1958 __ Ret(); | 1946 __ Ret(); |
1959 } | 1947 } |
1960 | 1948 |
1961 } // namespace dart | 1949 } // namespace dart |
1962 | 1950 |
1963 #endif // defined TARGET_ARCH_ARM | 1951 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |