| 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" | 5 #include "vm/globals.h" |
| 6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
| 7 | 7 |
| 8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
| 9 #include "vm/simulator.h" | 9 #include "vm/simulator.h" |
| 10 #include "vm/runtime_entry.h" | 10 #include "vm/runtime_entry.h" |
| (...skipping 1201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1212 void Assembler::vmstat(Condition cond) { // VMRS APSR_nzcv, FPSCR | 1212 void Assembler::vmstat(Condition cond) { // VMRS APSR_nzcv, FPSCR |
| 1213 ASSERT(cond != kNoCondition); | 1213 ASSERT(cond != kNoCondition); |
| 1214 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | | 1214 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | |
| 1215 B27 | B26 | B25 | B23 | B22 | B21 | B20 | B16 | | 1215 B27 | B26 | B25 | B23 | B22 | B21 | B20 | B16 | |
| 1216 (static_cast<int32_t>(PC)*B12) | | 1216 (static_cast<int32_t>(PC)*B12) | |
| 1217 B11 | B9 | B4; | 1217 B11 | B9 | B4; |
| 1218 Emit(encoding); | 1218 Emit(encoding); |
| 1219 } | 1219 } |
| 1220 | 1220 |
| 1221 | 1221 |
| 1222 void Assembler::EmitSIMDqqq(int32_t opcode, int sz, | 1222 void Assembler::EmitSIMDqqq(int32_t opcode, OperandSize size, |
| 1223 QRegister qd, QRegister qn, QRegister qm) { | 1223 QRegister qd, QRegister qn, QRegister qm) { |
| 1224 int sz = 0; |
| 1225 switch (size) { |
| 1226 case kByte: |
| 1227 case kUnsignedByte: |
| 1228 sz = 0; |
| 1229 break; |
| 1230 case kHalfword: |
| 1231 case kUnsignedHalfword: |
| 1232 sz = 1; |
| 1233 break; |
| 1234 case kWord: |
| 1235 case kUnsignedWord: |
| 1236 sz = 2; |
| 1237 break; |
| 1238 case kWordPair: |
| 1239 sz = 3; |
| 1240 break; |
| 1241 case kSWord: |
| 1242 case kDWord: |
| 1243 sz = 0; |
| 1244 break; |
| 1245 default: |
| 1246 UNREACHABLE(); |
| 1247 break; |
| 1248 } |
| 1224 int32_t encoding = | 1249 int32_t encoding = |
| 1225 (static_cast<int32_t>(kSpecialCondition) << kConditionShift) | | 1250 (static_cast<int32_t>(kSpecialCondition) << kConditionShift) | |
| 1226 B25 | B6 | | 1251 B25 | B6 | |
| 1227 opcode | ((sz & 0x3) * B20) | | 1252 opcode | ((sz & 0x3) * B20) | |
| 1228 ((static_cast<int32_t>(qd * 2) >> 4)*B22) | | 1253 ((static_cast<int32_t>(qd * 2) >> 4)*B22) | |
| 1229 ((static_cast<int32_t>(qn * 2) & 0xf)*B16) | | 1254 ((static_cast<int32_t>(qn * 2) & 0xf)*B16) | |
| 1230 ((static_cast<int32_t>(qd * 2) & 0xf)*B12) | | 1255 ((static_cast<int32_t>(qd * 2) & 0xf)*B12) | |
| 1231 ((static_cast<int32_t>(qn * 2) >> 4)*B7) | | 1256 ((static_cast<int32_t>(qn * 2) >> 4)*B7) | |
| 1232 ((static_cast<int32_t>(qm * 2) >> 4)*B5) | | 1257 ((static_cast<int32_t>(qm * 2) >> 4)*B5) | |
| 1233 (static_cast<int32_t>(qm * 2) & 0xf); | 1258 (static_cast<int32_t>(qm * 2) & 0xf); |
| 1234 Emit(encoding); | 1259 Emit(encoding); |
| 1235 } | 1260 } |
| 1236 | 1261 |
| 1237 | 1262 |
| 1238 void Assembler::vaddqi(int sz, QRegister qd, QRegister qn, QRegister qm) { | 1263 void Assembler::vaddqi(OperandSize sz, |
| 1239 ASSERT((sz >= 0) && (sz <= 3)); | 1264 QRegister qd, QRegister qn, QRegister qm) { |
| 1240 EmitSIMDqqq(B11, sz, qd, qn, qm); | 1265 EmitSIMDqqq(B11, sz, qd, qn, qm); |
| 1241 } | 1266 } |
| 1242 | 1267 |
| 1243 | 1268 |
| 1244 void Assembler::vaddqs(QRegister qd, QRegister qn, QRegister qm) { | 1269 void Assembler::vaddqs(QRegister qd, QRegister qn, QRegister qm) { |
| 1245 EmitSIMDqqq(B11 | B10 | B8, 0, qd, qn, qm); | 1270 EmitSIMDqqq(B11 | B10 | B8, kSWord, qd, qn, qm); |
| 1246 } | 1271 } |
| 1247 | 1272 |
| 1248 | 1273 |
| 1249 void Assembler::vsubqi(int sz, QRegister qd, QRegister qn, QRegister qm) { | 1274 void Assembler::vsubqi(OperandSize sz, |
| 1250 ASSERT((sz >= 0) && (sz <= 3)); | 1275 QRegister qd, QRegister qn, QRegister qm) { |
| 1251 EmitSIMDqqq(B24 | B11, sz, qd, qn, qm); | 1276 EmitSIMDqqq(B24 | B11, sz, qd, qn, qm); |
| 1252 } | 1277 } |
| 1253 | 1278 |
| 1254 | 1279 |
| 1255 void Assembler::vsubqs(QRegister qd, QRegister qn, QRegister qm) { | 1280 void Assembler::vsubqs(QRegister qd, QRegister qn, QRegister qm) { |
| 1256 EmitSIMDqqq(B21 | B11 | B10 | B8, 0, qd, qn, qm); | 1281 EmitSIMDqqq(B21 | B11 | B10 | B8, kSWord, qd, qn, qm); |
| 1257 } | 1282 } |
| 1258 | 1283 |
| 1259 | 1284 |
| 1260 void Assembler::vmulqi(int sz, QRegister qd, QRegister qn, QRegister qm) { | 1285 void Assembler::vmulqi(OperandSize sz, |
| 1261 ASSERT((sz >= 0) && (sz <= 2)); | 1286 QRegister qd, QRegister qn, QRegister qm) { |
| 1262 EmitSIMDqqq(B11 | B8 | B4, sz, qd, qn, qm); | 1287 EmitSIMDqqq(B11 | B8 | B4, sz, qd, qn, qm); |
| 1263 } | 1288 } |
| 1264 | 1289 |
| 1265 | 1290 |
| 1266 void Assembler::vmulqs(QRegister qd, QRegister qn, QRegister qm) { | 1291 void Assembler::vmulqs(QRegister qd, QRegister qn, QRegister qm) { |
| 1267 EmitSIMDqqq(B24 | B11 | B10 | B8 | B4, 0, qd, qn, qm); | 1292 EmitSIMDqqq(B24 | B11 | B10 | B8 | B4, kSWord, qd, qn, qm); |
| 1268 } | 1293 } |
| 1269 | 1294 |
| 1270 | 1295 |
| 1271 void Assembler::svc(uint32_t imm24, Condition cond) { | 1296 void Assembler::svc(uint32_t imm24, Condition cond) { |
| 1272 ASSERT(cond != kNoCondition); | 1297 ASSERT(cond != kNoCondition); |
| 1273 ASSERT(imm24 < (1 << 24)); | 1298 ASSERT(imm24 < (1 << 24)); |
| 1274 int32_t encoding = (cond << kConditionShift) | B27 | B26 | B25 | B24 | imm24; | 1299 int32_t encoding = (cond << kConditionShift) | B27 | B26 | B25 | B24 | imm24; |
| 1275 Emit(encoding); | 1300 Emit(encoding); |
| 1276 } | 1301 } |
| 1277 | 1302 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1330 } | 1355 } |
| 1331 } | 1356 } |
| 1332 | 1357 |
| 1333 | 1358 |
| 1334 // Uses a code sequence that can easily be decoded. | 1359 // Uses a code sequence that can easily be decoded. |
| 1335 void Assembler::LoadWordFromPoolOffset(Register rd, | 1360 void Assembler::LoadWordFromPoolOffset(Register rd, |
| 1336 int32_t offset, | 1361 int32_t offset, |
| 1337 Condition cond) { | 1362 Condition cond) { |
| 1338 ASSERT(rd != PP); | 1363 ASSERT(rd != PP); |
| 1339 int32_t offset_mask = 0; | 1364 int32_t offset_mask = 0; |
| 1340 if (Address::CanHoldLoadOffset(kLoadWord, offset, &offset_mask)) { | 1365 if (Address::CanHoldLoadOffset(kWord, offset, &offset_mask)) { |
| 1341 ldr(rd, Address(PP, offset), cond); | 1366 ldr(rd, Address(PP, offset), cond); |
| 1342 } else { | 1367 } else { |
| 1343 int32_t offset_hi = offset & ~offset_mask; // signed | 1368 int32_t offset_hi = offset & ~offset_mask; // signed |
| 1344 uint32_t offset_lo = offset & offset_mask; // unsigned | 1369 uint32_t offset_lo = offset & offset_mask; // unsigned |
| 1345 // Inline a simplified version of AddImmediate(rd, PP, offset_hi). | 1370 // Inline a simplified version of AddImmediate(rd, PP, offset_hi). |
| 1346 ShifterOperand shifter_op; | 1371 ShifterOperand shifter_op; |
| 1347 if (ShifterOperand::CanHold(offset_hi, &shifter_op)) { | 1372 if (ShifterOperand::CanHold(offset_hi, &shifter_op)) { |
| 1348 add(rd, PP, shifter_op, cond); | 1373 add(rd, PP, shifter_op, cond); |
| 1349 } else { | 1374 } else { |
| 1350 movw(rd, Utils::Low16Bits(offset_hi)); | 1375 movw(rd, Utils::Low16Bits(offset_hi)); |
| 1351 const uint16_t value_high = Utils::High16Bits(offset_hi); | 1376 const uint16_t value_high = Utils::High16Bits(offset_hi); |
| 1352 if (value_high != 0) { | 1377 if (value_high != 0) { |
| 1353 movt(rd, value_high, cond); | 1378 movt(rd, value_high, cond); |
| 1354 } | 1379 } |
| 1355 add(rd, PP, ShifterOperand(LR), cond); | 1380 add(rd, PP, ShifterOperand(LR), cond); |
| 1356 } | 1381 } |
| 1357 ldr(rd, Address(rd, offset_lo), cond); | 1382 ldr(rd, Address(rd, offset_lo), cond); |
| 1358 } | 1383 } |
| 1359 } | 1384 } |
| 1360 | 1385 |
| 1361 | 1386 |
| 1362 void Assembler::LoadPoolPointer() { | 1387 void Assembler::LoadPoolPointer() { |
| 1363 const intptr_t object_pool_pc_dist = | 1388 const intptr_t object_pool_pc_dist = |
| 1364 Instructions::HeaderSize() - Instructions::object_pool_offset() + | 1389 Instructions::HeaderSize() - Instructions::object_pool_offset() + |
| 1365 CodeSize() + Instr::kPCReadOffset; | 1390 CodeSize() + Instr::kPCReadOffset; |
| 1366 LoadFromOffset(kLoadWord, PP, PC, -object_pool_pc_dist); | 1391 LoadFromOffset(kWord, PP, PC, -object_pool_pc_dist); |
| 1367 } | 1392 } |
| 1368 | 1393 |
| 1369 | 1394 |
| 1370 void Assembler::LoadObject(Register rd, const Object& object, Condition cond) { | 1395 void Assembler::LoadObject(Register rd, const Object& object, Condition cond) { |
| 1371 // Smis and VM heap objects are never relocated; do not use object pool. | 1396 // Smis and VM heap objects are never relocated; do not use object pool. |
| 1372 if (object.IsSmi()) { | 1397 if (object.IsSmi()) { |
| 1373 LoadImmediate(rd, reinterpret_cast<int32_t>(object.raw()), cond); | 1398 LoadImmediate(rd, reinterpret_cast<int32_t>(object.raw()), cond); |
| 1374 } else if (object.InVMHeap()) { | 1399 } else if (object.InVMHeap()) { |
| 1375 // Make sure that class CallPattern is able to decode this load immediate. | 1400 // Make sure that class CallPattern is able to decode this load immediate. |
| 1376 const int32_t object_raw = reinterpret_cast<int32_t>(object.raw()); | 1401 const int32_t object_raw = reinterpret_cast<int32_t>(object.raw()); |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1492 RawObject::kClassIdTagBit / kBitsPerByte; | 1517 RawObject::kClassIdTagBit / kBitsPerByte; |
| 1493 ldrh(result, FieldAddress(object, class_id_offset)); | 1518 ldrh(result, FieldAddress(object, class_id_offset)); |
| 1494 } | 1519 } |
| 1495 | 1520 |
| 1496 | 1521 |
| 1497 void Assembler::LoadClassById(Register result, Register class_id) { | 1522 void Assembler::LoadClassById(Register result, Register class_id) { |
| 1498 ASSERT(result != class_id); | 1523 ASSERT(result != class_id); |
| 1499 ldr(result, FieldAddress(CTX, Context::isolate_offset())); | 1524 ldr(result, FieldAddress(CTX, Context::isolate_offset())); |
| 1500 const intptr_t table_offset_in_isolate = | 1525 const intptr_t table_offset_in_isolate = |
| 1501 Isolate::class_table_offset() + ClassTable::table_offset(); | 1526 Isolate::class_table_offset() + ClassTable::table_offset(); |
| 1502 LoadFromOffset(kLoadWord, result, result, table_offset_in_isolate); | 1527 LoadFromOffset(kWord, result, result, table_offset_in_isolate); |
| 1503 ldr(result, Address(result, class_id, LSL, 2)); | 1528 ldr(result, Address(result, class_id, LSL, 2)); |
| 1504 } | 1529 } |
| 1505 | 1530 |
| 1506 | 1531 |
| 1507 void Assembler::LoadClass(Register result, Register object, Register scratch) { | 1532 void Assembler::LoadClass(Register result, Register object, Register scratch) { |
| 1508 ASSERT(scratch != result); | 1533 ASSERT(scratch != result); |
| 1509 LoadClassId(scratch, object); | 1534 LoadClassId(scratch, object); |
| 1510 | 1535 |
| 1511 ldr(result, FieldAddress(CTX, Context::isolate_offset())); | 1536 ldr(result, FieldAddress(CTX, Context::isolate_offset())); |
| 1512 const intptr_t table_offset_in_isolate = | 1537 const intptr_t table_offset_in_isolate = |
| 1513 Isolate::class_table_offset() + ClassTable::table_offset(); | 1538 Isolate::class_table_offset() + ClassTable::table_offset(); |
| 1514 LoadFromOffset(kLoadWord, result, result, table_offset_in_isolate); | 1539 LoadFromOffset(kWord, result, result, table_offset_in_isolate); |
| 1515 ldr(result, Address(result, scratch, LSL, 2)); | 1540 ldr(result, Address(result, scratch, LSL, 2)); |
| 1516 } | 1541 } |
| 1517 | 1542 |
| 1518 | 1543 |
| 1519 void Assembler::CompareClassId(Register object, | 1544 void Assembler::CompareClassId(Register object, |
| 1520 intptr_t class_id, | 1545 intptr_t class_id, |
| 1521 Register scratch) { | 1546 Register scratch) { |
| 1522 LoadClassId(scratch, object); | 1547 LoadClassId(scratch, object); |
| 1523 CompareImmediate(scratch, class_id); | 1548 CompareImmediate(scratch, class_id); |
| 1524 } | 1549 } |
| 1525 | 1550 |
| 1526 | 1551 |
| 1527 void Assembler::Bind(Label* label) { | 1552 void Assembler::Bind(Label* label) { |
| 1528 ASSERT(!label->IsBound()); | 1553 ASSERT(!label->IsBound()); |
| 1529 int bound_pc = buffer_.Size(); | 1554 int bound_pc = buffer_.Size(); |
| 1530 while (label->IsLinked()) { | 1555 while (label->IsLinked()) { |
| 1531 int32_t position = label->Position(); | 1556 int32_t position = label->Position(); |
| 1532 int32_t next = buffer_.Load<int32_t>(position); | 1557 int32_t next = buffer_.Load<int32_t>(position); |
| 1533 int32_t encoded = Assembler::EncodeBranchOffset(bound_pc - position, next); | 1558 int32_t encoded = Assembler::EncodeBranchOffset(bound_pc - position, next); |
| 1534 buffer_.Store<int32_t>(position, encoded); | 1559 buffer_.Store<int32_t>(position, encoded); |
| 1535 label->position_ = Assembler::DecodeBranchOffset(next); | 1560 label->position_ = Assembler::DecodeBranchOffset(next); |
| 1536 } | 1561 } |
| 1537 label->BindTo(bound_pc); | 1562 label->BindTo(bound_pc); |
| 1538 } | 1563 } |
| 1539 | 1564 |
| 1540 | 1565 |
| 1541 bool Address::CanHoldLoadOffset(LoadOperandType type, | 1566 bool Address::CanHoldLoadOffset(OperandSize type, |
| 1542 int32_t offset, | 1567 int32_t offset, |
| 1543 int32_t* offset_mask) { | 1568 int32_t* offset_mask) { |
| 1544 switch (type) { | 1569 switch (type) { |
| 1545 case kLoadSignedByte: | 1570 case kByte: |
| 1546 case kLoadSignedHalfword: | 1571 case kHalfword: |
| 1547 case kLoadUnsignedHalfword: | 1572 case kUnsignedHalfword: |
| 1548 case kLoadWordPair: { | 1573 case kWordPair: { |
| 1549 *offset_mask = 0xff; | 1574 *offset_mask = 0xff; |
| 1550 return Utils::IsAbsoluteUint(8, offset); // Addressing mode 3. | 1575 return Utils::IsAbsoluteUint(8, offset); // Addressing mode 3. |
| 1551 } | 1576 } |
| 1552 case kLoadUnsignedByte: | 1577 case kUnsignedByte: |
| 1553 case kLoadWord: { | 1578 case kWord: { |
| 1554 *offset_mask = 0xfff; | 1579 *offset_mask = 0xfff; |
| 1555 return Utils::IsAbsoluteUint(12, offset); // Addressing mode 2. | 1580 return Utils::IsAbsoluteUint(12, offset); // Addressing mode 2. |
| 1556 } | 1581 } |
| 1557 case kLoadSWord: | 1582 case kSWord: |
| 1558 case kLoadDWord: { | 1583 case kDWord: { |
| 1559 *offset_mask = 0x3fc; // Multiple of 4. | 1584 *offset_mask = 0x3fc; // Multiple of 4. |
| 1560 // VFP addressing mode. | 1585 // VFP addressing mode. |
| 1561 return (Utils::IsAbsoluteUint(10, offset) && Utils::IsAligned(offset, 4)); | 1586 return (Utils::IsAbsoluteUint(10, offset) && Utils::IsAligned(offset, 4)); |
| 1562 } | 1587 } |
| 1563 default: { | 1588 default: { |
| 1564 UNREACHABLE(); | 1589 UNREACHABLE(); |
| 1565 return false; | 1590 return false; |
| 1566 } | 1591 } |
| 1567 } | 1592 } |
| 1568 } | 1593 } |
| 1569 | 1594 |
| 1570 | 1595 |
| 1571 bool Address::CanHoldStoreOffset(StoreOperandType type, | 1596 bool Address::CanHoldStoreOffset(OperandSize type, |
| 1572 int32_t offset, | 1597 int32_t offset, |
| 1573 int32_t* offset_mask) { | 1598 int32_t* offset_mask) { |
| 1574 switch (type) { | 1599 switch (type) { |
| 1575 case kStoreHalfword: | 1600 case kHalfword: |
| 1576 case kStoreWordPair: { | 1601 case kWordPair: { |
| 1577 *offset_mask = 0xff; | 1602 *offset_mask = 0xff; |
| 1578 return Utils::IsAbsoluteUint(8, offset); // Addressing mode 3. | 1603 return Utils::IsAbsoluteUint(8, offset); // Addressing mode 3. |
| 1579 } | 1604 } |
| 1580 case kStoreByte: | 1605 case kByte: |
| 1581 case kStoreWord: { | 1606 case kWord: { |
| 1582 *offset_mask = 0xfff; | 1607 *offset_mask = 0xfff; |
| 1583 return Utils::IsAbsoluteUint(12, offset); // Addressing mode 2. | 1608 return Utils::IsAbsoluteUint(12, offset); // Addressing mode 2. |
| 1584 } | 1609 } |
| 1585 case kStoreSWord: | 1610 case kSWord: |
| 1586 case kStoreDWord: { | 1611 case kDWord: { |
| 1587 *offset_mask = 0x3fc; // Multiple of 4. | 1612 *offset_mask = 0x3fc; // Multiple of 4. |
| 1588 // VFP addressing mode. | 1613 // VFP addressing mode. |
| 1589 return (Utils::IsAbsoluteUint(10, offset) && Utils::IsAligned(offset, 4)); | 1614 return (Utils::IsAbsoluteUint(10, offset) && Utils::IsAligned(offset, 4)); |
| 1590 } | 1615 } |
| 1591 default: { | 1616 default: { |
| 1592 UNREACHABLE(); | 1617 UNREACHABLE(); |
| 1593 return false; | 1618 return false; |
| 1594 } | 1619 } |
| 1595 } | 1620 } |
| 1596 } | 1621 } |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1717 // TODO(regis): Revisit this code sequence. | 1742 // TODO(regis): Revisit this code sequence. |
| 1718 LoadImmediate(IP, label->address()); // Target address is never patched. | 1743 LoadImmediate(IP, label->address()); // Target address is never patched. |
| 1719 str(PC, ad); | 1744 str(PC, ad); |
| 1720 blx(IP); // Use blx instruction so that the return branch prediction works. | 1745 blx(IP); // Use blx instruction so that the return branch prediction works. |
| 1721 } | 1746 } |
| 1722 | 1747 |
| 1723 | 1748 |
| 1724 void Assembler::BranchLinkOffset(Register base, int32_t offset) { | 1749 void Assembler::BranchLinkOffset(Register base, int32_t offset) { |
| 1725 ASSERT(base != PC); | 1750 ASSERT(base != PC); |
| 1726 ASSERT(base != IP); | 1751 ASSERT(base != IP); |
| 1727 LoadFromOffset(kLoadWord, IP, base, offset); | 1752 LoadFromOffset(kWord, IP, base, offset); |
| 1728 blx(IP); // Use blx instruction so that the return branch prediction works. | 1753 blx(IP); // Use blx instruction so that the return branch prediction works. |
| 1729 } | 1754 } |
| 1730 | 1755 |
| 1731 | 1756 |
| 1732 void Assembler::LoadImmediate(Register rd, int32_t value, Condition cond) { | 1757 void Assembler::LoadImmediate(Register rd, int32_t value, Condition cond) { |
| 1733 ShifterOperand shifter_op; | 1758 ShifterOperand shifter_op; |
| 1734 if (ShifterOperand::CanHold(value, &shifter_op)) { | 1759 if (ShifterOperand::CanHold(value, &shifter_op)) { |
| 1735 mov(rd, shifter_op, cond); | 1760 mov(rd, shifter_op, cond); |
| 1736 } else if (ShifterOperand::CanHold(~value, &shifter_op)) { | 1761 } else if (ShifterOperand::CanHold(~value, &shifter_op)) { |
| 1737 mvn(rd, shifter_op, cond); | 1762 mvn(rd, shifter_op, cond); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1764 // A scratch register and IP are needed to load an arbitrary double. | 1789 // A scratch register and IP are needed to load an arbitrary double. |
| 1765 ASSERT(scratch != kNoRegister); | 1790 ASSERT(scratch != kNoRegister); |
| 1766 int64_t imm64 = bit_cast<int64_t, double>(value); | 1791 int64_t imm64 = bit_cast<int64_t, double>(value); |
| 1767 LoadImmediate(IP, Utils::Low32Bits(imm64), cond); | 1792 LoadImmediate(IP, Utils::Low32Bits(imm64), cond); |
| 1768 LoadImmediate(scratch, Utils::High32Bits(imm64), cond); | 1793 LoadImmediate(scratch, Utils::High32Bits(imm64), cond); |
| 1769 vmovdrr(dd, IP, scratch, cond); | 1794 vmovdrr(dd, IP, scratch, cond); |
| 1770 } | 1795 } |
| 1771 } | 1796 } |
| 1772 | 1797 |
| 1773 | 1798 |
| 1774 void Assembler::LoadFromOffset(LoadOperandType type, | 1799 void Assembler::LoadFromOffset(OperandSize type, |
| 1775 Register reg, | 1800 Register reg, |
| 1776 Register base, | 1801 Register base, |
| 1777 int32_t offset, | 1802 int32_t offset, |
| 1778 Condition cond) { | 1803 Condition cond) { |
| 1779 int32_t offset_mask = 0; | 1804 int32_t offset_mask = 0; |
| 1780 if (!Address::CanHoldLoadOffset(type, offset, &offset_mask)) { | 1805 if (!Address::CanHoldLoadOffset(type, offset, &offset_mask)) { |
| 1781 ASSERT(base != IP); | 1806 ASSERT(base != IP); |
| 1782 AddImmediate(IP, base, offset & ~offset_mask, cond); | 1807 AddImmediate(IP, base, offset & ~offset_mask, cond); |
| 1783 base = IP; | 1808 base = IP; |
| 1784 offset = offset & offset_mask; | 1809 offset = offset & offset_mask; |
| 1785 } | 1810 } |
| 1786 switch (type) { | 1811 switch (type) { |
| 1787 case kLoadSignedByte: | 1812 case kByte: |
| 1788 ldrsb(reg, Address(base, offset), cond); | 1813 ldrsb(reg, Address(base, offset), cond); |
| 1789 break; | 1814 break; |
| 1790 case kLoadUnsignedByte: | 1815 case kUnsignedByte: |
| 1791 ldrb(reg, Address(base, offset), cond); | 1816 ldrb(reg, Address(base, offset), cond); |
| 1792 break; | 1817 break; |
| 1793 case kLoadSignedHalfword: | 1818 case kHalfword: |
| 1794 ldrsh(reg, Address(base, offset), cond); | 1819 ldrsh(reg, Address(base, offset), cond); |
| 1795 break; | 1820 break; |
| 1796 case kLoadUnsignedHalfword: | 1821 case kUnsignedHalfword: |
| 1797 ldrh(reg, Address(base, offset), cond); | 1822 ldrh(reg, Address(base, offset), cond); |
| 1798 break; | 1823 break; |
| 1799 case kLoadWord: | 1824 case kWord: |
| 1800 ldr(reg, Address(base, offset), cond); | 1825 ldr(reg, Address(base, offset), cond); |
| 1801 break; | 1826 break; |
| 1802 case kLoadWordPair: | 1827 case kWordPair: |
| 1803 ldrd(reg, Address(base, offset), cond); | 1828 ldrd(reg, Address(base, offset), cond); |
| 1804 break; | 1829 break; |
| 1805 default: | 1830 default: |
| 1806 UNREACHABLE(); | 1831 UNREACHABLE(); |
| 1807 } | 1832 } |
| 1808 } | 1833 } |
| 1809 | 1834 |
| 1810 | 1835 |
| 1811 void Assembler::StoreToOffset(StoreOperandType type, | 1836 void Assembler::StoreToOffset(OperandSize type, |
| 1812 Register reg, | 1837 Register reg, |
| 1813 Register base, | 1838 Register base, |
| 1814 int32_t offset, | 1839 int32_t offset, |
| 1815 Condition cond) { | 1840 Condition cond) { |
| 1816 int32_t offset_mask = 0; | 1841 int32_t offset_mask = 0; |
| 1817 if (!Address::CanHoldStoreOffset(type, offset, &offset_mask)) { | 1842 if (!Address::CanHoldStoreOffset(type, offset, &offset_mask)) { |
| 1818 ASSERT(reg != IP); | 1843 ASSERT(reg != IP); |
| 1819 ASSERT(base != IP); | 1844 ASSERT(base != IP); |
| 1820 AddImmediate(IP, base, offset & ~offset_mask, cond); | 1845 AddImmediate(IP, base, offset & ~offset_mask, cond); |
| 1821 base = IP; | 1846 base = IP; |
| 1822 offset = offset & offset_mask; | 1847 offset = offset & offset_mask; |
| 1823 } | 1848 } |
| 1824 switch (type) { | 1849 switch (type) { |
| 1825 case kStoreByte: | 1850 case kByte: |
| 1826 strb(reg, Address(base, offset), cond); | 1851 strb(reg, Address(base, offset), cond); |
| 1827 break; | 1852 break; |
| 1828 case kStoreHalfword: | 1853 case kHalfword: |
| 1829 strh(reg, Address(base, offset), cond); | 1854 strh(reg, Address(base, offset), cond); |
| 1830 break; | 1855 break; |
| 1831 case kStoreWord: | 1856 case kWord: |
| 1832 str(reg, Address(base, offset), cond); | 1857 str(reg, Address(base, offset), cond); |
| 1833 break; | 1858 break; |
| 1834 case kStoreWordPair: | 1859 case kWordPair: |
| 1835 strd(reg, Address(base, offset), cond); | 1860 strd(reg, Address(base, offset), cond); |
| 1836 break; | 1861 break; |
| 1837 default: | 1862 default: |
| 1838 UNREACHABLE(); | 1863 UNREACHABLE(); |
| 1839 } | 1864 } |
| 1840 } | 1865 } |
| 1841 | 1866 |
| 1842 | 1867 |
| 1843 void Assembler::LoadSFromOffset(SRegister reg, | 1868 void Assembler::LoadSFromOffset(SRegister reg, |
| 1844 Register base, | 1869 Register base, |
| 1845 int32_t offset, | 1870 int32_t offset, |
| 1846 Condition cond) { | 1871 Condition cond) { |
| 1847 int32_t offset_mask = 0; | 1872 int32_t offset_mask = 0; |
| 1848 if (!Address::CanHoldLoadOffset(kLoadSWord, offset, &offset_mask)) { | 1873 if (!Address::CanHoldLoadOffset(kSWord, offset, &offset_mask)) { |
| 1849 ASSERT(base != IP); | 1874 ASSERT(base != IP); |
| 1850 AddImmediate(IP, base, offset & ~offset_mask, cond); | 1875 AddImmediate(IP, base, offset & ~offset_mask, cond); |
| 1851 base = IP; | 1876 base = IP; |
| 1852 offset = offset & offset_mask; | 1877 offset = offset & offset_mask; |
| 1853 } | 1878 } |
| 1854 vldrs(reg, Address(base, offset), cond); | 1879 vldrs(reg, Address(base, offset), cond); |
| 1855 } | 1880 } |
| 1856 | 1881 |
| 1857 | 1882 |
| 1858 void Assembler::StoreSToOffset(SRegister reg, | 1883 void Assembler::StoreSToOffset(SRegister reg, |
| 1859 Register base, | 1884 Register base, |
| 1860 int32_t offset, | 1885 int32_t offset, |
| 1861 Condition cond) { | 1886 Condition cond) { |
| 1862 int32_t offset_mask = 0; | 1887 int32_t offset_mask = 0; |
| 1863 if (!Address::CanHoldStoreOffset(kStoreSWord, offset, &offset_mask)) { | 1888 if (!Address::CanHoldStoreOffset(kSWord, offset, &offset_mask)) { |
| 1864 ASSERT(base != IP); | 1889 ASSERT(base != IP); |
| 1865 AddImmediate(IP, base, offset & ~offset_mask, cond); | 1890 AddImmediate(IP, base, offset & ~offset_mask, cond); |
| 1866 base = IP; | 1891 base = IP; |
| 1867 offset = offset & offset_mask; | 1892 offset = offset & offset_mask; |
| 1868 } | 1893 } |
| 1869 vstrs(reg, Address(base, offset), cond); | 1894 vstrs(reg, Address(base, offset), cond); |
| 1870 } | 1895 } |
| 1871 | 1896 |
| 1872 | 1897 |
| 1873 void Assembler::LoadDFromOffset(DRegister reg, | 1898 void Assembler::LoadDFromOffset(DRegister reg, |
| 1874 Register base, | 1899 Register base, |
| 1875 int32_t offset, | 1900 int32_t offset, |
| 1876 Condition cond) { | 1901 Condition cond) { |
| 1877 int32_t offset_mask = 0; | 1902 int32_t offset_mask = 0; |
| 1878 if (!Address::CanHoldLoadOffset(kLoadDWord, offset, &offset_mask)) { | 1903 if (!Address::CanHoldLoadOffset(kDWord, offset, &offset_mask)) { |
| 1879 ASSERT(base != IP); | 1904 ASSERT(base != IP); |
| 1880 AddImmediate(IP, base, offset & ~offset_mask, cond); | 1905 AddImmediate(IP, base, offset & ~offset_mask, cond); |
| 1881 base = IP; | 1906 base = IP; |
| 1882 offset = offset & offset_mask; | 1907 offset = offset & offset_mask; |
| 1883 } | 1908 } |
| 1884 vldrd(reg, Address(base, offset), cond); | 1909 vldrd(reg, Address(base, offset), cond); |
| 1885 } | 1910 } |
| 1886 | 1911 |
| 1887 | 1912 |
| 1888 void Assembler::StoreDToOffset(DRegister reg, | 1913 void Assembler::StoreDToOffset(DRegister reg, |
| 1889 Register base, | 1914 Register base, |
| 1890 int32_t offset, | 1915 int32_t offset, |
| 1891 Condition cond) { | 1916 Condition cond) { |
| 1892 int32_t offset_mask = 0; | 1917 int32_t offset_mask = 0; |
| 1893 if (!Address::CanHoldStoreOffset(kStoreDWord, offset, &offset_mask)) { | 1918 if (!Address::CanHoldStoreOffset(kDWord, offset, &offset_mask)) { |
| 1894 ASSERT(base != IP); | 1919 ASSERT(base != IP); |
| 1895 AddImmediate(IP, base, offset & ~offset_mask, cond); | 1920 AddImmediate(IP, base, offset & ~offset_mask, cond); |
| 1896 base = IP; | 1921 base = IP; |
| 1897 offset = offset & offset_mask; | 1922 offset = offset & offset_mask; |
| 1898 } | 1923 } |
| 1899 vstrd(reg, Address(base, offset), cond); | 1924 vstrd(reg, Address(base, offset), cond); |
| 1900 } | 1925 } |
| 1901 | 1926 |
| 1902 | 1927 |
| 1903 void Assembler::AddImmediate(Register rd, int32_t value, Condition cond) { | 1928 void Assembler::AddImmediate(Register rd, int32_t value, Condition cond) { |
| (...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2323 | 2348 |
| 2324 const char* Assembler::FpuRegisterName(FpuRegister reg) { | 2349 const char* Assembler::FpuRegisterName(FpuRegister reg) { |
| 2325 ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters)); | 2350 ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters)); |
| 2326 return fpu_reg_names[reg]; | 2351 return fpu_reg_names[reg]; |
| 2327 } | 2352 } |
| 2328 | 2353 |
| 2329 } // namespace dart | 2354 } // namespace dart |
| 2330 | 2355 |
| 2331 #endif // defined TARGET_ARCH_ARM | 2356 #endif // defined TARGET_ARCH_ARM |
| 2332 | 2357 |
| OLD | NEW |