Chromium Code Reviews| 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" |
| 11 #include "vm/stub_code.h" | 11 #include "vm/stub_code.h" |
| 12 | 12 |
| 13 namespace dart { | 13 namespace dart { |
| 14 | 14 |
| 15 // TODO(regis): Enable this flag after PrintStopMessage stub is implemented. | 15 DEFINE_FLAG(bool, print_stop_message, true, "Print stop message."); |
| 16 DEFINE_FLAG(bool, print_stop_message, false, "Print stop message."); | |
| 17 | 16 |
| 18 | 17 |
| 19 bool CPUFeatures::integer_division_supported_ = false; | 18 bool CPUFeatures::integer_division_supported_ = false; |
| 20 #if defined(DEBUG) | 19 #if defined(DEBUG) |
| 21 bool CPUFeatures::initialized_ = false; | 20 bool CPUFeatures::initialized_ = false; |
| 22 #endif | 21 #endif |
| 23 | 22 |
| 24 | 23 |
| 25 bool CPUFeatures::integer_division_supported() { | 24 bool CPUFeatures::integer_division_supported() { |
| 26 DEBUG_ASSERT(initialized_); | 25 DEBUG_ASSERT(initialized_); |
| (...skipping 1215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1242 if (object.IsNull() || | 1241 if (object.IsNull() || |
| 1243 object.IsSmi() || | 1242 object.IsSmi() || |
| 1244 (object.raw() == Bool::True().raw()) || | 1243 (object.raw() == Bool::True().raw()) || |
| 1245 (object.raw() == Bool::False().raw())) { | 1244 (object.raw() == Bool::False().raw())) { |
| 1246 // This object is never relocated; do not use object pool. | 1245 // This object is never relocated; do not use object pool. |
| 1247 LoadImmediate(rd, reinterpret_cast<int32_t>(object.raw())); | 1246 LoadImmediate(rd, reinterpret_cast<int32_t>(object.raw())); |
| 1248 return; | 1247 return; |
| 1249 } | 1248 } |
| 1250 const int32_t offset = | 1249 const int32_t offset = |
| 1251 Array::data_offset() + 4*AddObject(object) - kHeapObjectTag; | 1250 Array::data_offset() + 4*AddObject(object) - kHeapObjectTag; |
| 1252 if (Address::CanHoldLoadOffset(kLoadWord, offset)) { | 1251 int32_t offset_mask; |
| 1252 if (Address::CanHoldLoadOffset(kLoadWord, offset, &offset_mask)) { | |
| 1253 ldr(rd, Address(PP, offset)); | 1253 ldr(rd, Address(PP, offset)); |
| 1254 } else { | 1254 } else { |
| 1255 int32_t offset12_hi = offset & ~kOffset12Mask; // signed | 1255 int32_t offset_hi = offset & ~offset_mask; // signed |
| 1256 uint32_t offset12_lo = offset & kOffset12Mask; // unsigned | 1256 uint32_t offset_lo = offset & offset_mask; // unsigned |
|
zra
2013/03/06 16:41:27
ASSERT(CanHoldLoadOffset(offset_lo))
regis
2013/03/06 18:42:00
Actually, each instruction already asserts that th
| |
| 1257 AddImmediate(rd, PP, offset12_hi); | 1257 AddImmediate(rd, PP, offset_hi); |
| 1258 ldr(rd, Address(rd, offset12_lo)); | 1258 ldr(rd, Address(rd, offset_lo)); |
| 1259 } | 1259 } |
| 1260 } | 1260 } |
| 1261 | 1261 |
| 1262 | 1262 |
| 1263 void Assembler::Bind(Label* label) { | 1263 void Assembler::Bind(Label* label) { |
| 1264 ASSERT(!label->IsBound()); | 1264 ASSERT(!label->IsBound()); |
| 1265 int bound_pc = buffer_.Size(); | 1265 int bound_pc = buffer_.Size(); |
| 1266 while (label->IsLinked()) { | 1266 while (label->IsLinked()) { |
| 1267 int32_t position = label->Position(); | 1267 int32_t position = label->Position(); |
| 1268 int32_t next = buffer_.Load<int32_t>(position); | 1268 int32_t next = buffer_.Load<int32_t>(position); |
| 1269 int32_t encoded = Assembler::EncodeBranchOffset(bound_pc - position, next); | 1269 int32_t encoded = Assembler::EncodeBranchOffset(bound_pc - position, next); |
| 1270 buffer_.Store<int32_t>(position, encoded); | 1270 buffer_.Store<int32_t>(position, encoded); |
| 1271 label->position_ = Assembler::DecodeBranchOffset(next); | 1271 label->position_ = Assembler::DecodeBranchOffset(next); |
| 1272 } | 1272 } |
| 1273 label->BindTo(bound_pc); | 1273 label->BindTo(bound_pc); |
| 1274 } | 1274 } |
| 1275 | 1275 |
| 1276 | 1276 |
| 1277 bool Address::CanHoldLoadOffset(LoadOperandType type, int offset) { | 1277 bool Address::CanHoldLoadOffset(LoadOperandType type, |
|
zra
2013/03/06 03:30:28
I just want to double-check this and CanHoldStoreO
regis
2013/03/06 18:42:00
OK. I'll revisit if you find a problem.
| |
| 1278 int32_t offset, | |
| 1279 int32_t* offset_mask) { | |
| 1278 switch (type) { | 1280 switch (type) { |
| 1279 case kLoadSignedByte: | 1281 case kLoadSignedByte: |
| 1280 case kLoadSignedHalfword: | 1282 case kLoadSignedHalfword: |
| 1281 case kLoadUnsignedHalfword: | 1283 case kLoadUnsignedHalfword: |
| 1282 case kLoadWordPair: | 1284 case kLoadWordPair: { |
| 1285 *offset_mask = 0xff; | |
| 1283 return Utils::IsAbsoluteUint(8, offset); // Addressing mode 3. | 1286 return Utils::IsAbsoluteUint(8, offset); // Addressing mode 3. |
| 1287 } | |
| 1284 case kLoadUnsignedByte: | 1288 case kLoadUnsignedByte: |
| 1285 case kLoadWord: | 1289 case kLoadWord: { |
| 1290 *offset_mask = 0xfff; | |
| 1286 return Utils::IsAbsoluteUint(12, offset); // Addressing mode 2. | 1291 return Utils::IsAbsoluteUint(12, offset); // Addressing mode 2. |
| 1292 } | |
| 1287 case kLoadSWord: | 1293 case kLoadSWord: |
| 1288 case kLoadDWord: | 1294 case kLoadDWord: { |
| 1295 *offset_mask = 0x3ff; | |
| 1289 return Utils::IsAbsoluteUint(10, offset); // VFP addressing mode. | 1296 return Utils::IsAbsoluteUint(10, offset); // VFP addressing mode. |
| 1290 default: | 1297 } |
| 1298 default: { | |
| 1291 UNREACHABLE(); | 1299 UNREACHABLE(); |
| 1292 return false; | 1300 return false; |
| 1301 } | |
| 1293 } | 1302 } |
| 1294 } | 1303 } |
| 1295 | 1304 |
| 1296 | 1305 |
| 1297 bool Address::CanHoldStoreOffset(StoreOperandType type, int offset) { | 1306 bool Address::CanHoldStoreOffset(StoreOperandType type, |
| 1307 int32_t offset, | |
| 1308 int32_t* offset_mask) { | |
| 1298 switch (type) { | 1309 switch (type) { |
| 1299 case kStoreHalfword: | 1310 case kStoreHalfword: |
| 1300 case kStoreWordPair: | 1311 case kStoreWordPair: { |
| 1312 *offset_mask = 0xff; | |
| 1301 return Utils::IsAbsoluteUint(8, offset); // Addressing mode 3. | 1313 return Utils::IsAbsoluteUint(8, offset); // Addressing mode 3. |
| 1314 } | |
| 1302 case kStoreByte: | 1315 case kStoreByte: |
| 1303 case kStoreWord: | 1316 case kStoreWord: { |
| 1317 *offset_mask = 0xfff; | |
| 1304 return Utils::IsAbsoluteUint(12, offset); // Addressing mode 2. | 1318 return Utils::IsAbsoluteUint(12, offset); // Addressing mode 2. |
| 1319 } | |
| 1305 case kStoreSWord: | 1320 case kStoreSWord: |
| 1306 case kStoreDWord: | 1321 case kStoreDWord: { |
| 1322 *offset_mask = 0x3ff; | |
| 1307 return Utils::IsAbsoluteUint(10, offset); // VFP addressing mode. | 1323 return Utils::IsAbsoluteUint(10, offset); // VFP addressing mode. |
| 1308 default: | 1324 } |
| 1325 default: { | |
| 1309 UNREACHABLE(); | 1326 UNREACHABLE(); |
| 1310 return false; | 1327 return false; |
| 1328 } | |
| 1311 } | 1329 } |
| 1312 } | 1330 } |
| 1313 | 1331 |
| 1314 | 1332 |
| 1315 void Assembler::Push(Register rd, Condition cond) { | 1333 void Assembler::Push(Register rd, Condition cond) { |
| 1316 str(rd, Address(SP, -kWordSize, Address::PreIndex), cond); | 1334 str(rd, Address(SP, -kWordSize, Address::PreIndex), cond); |
| 1317 } | 1335 } |
| 1318 | 1336 |
| 1319 | 1337 |
| 1320 void Assembler::Pop(Register rd, Condition cond) { | 1338 void Assembler::Pop(Register rd, Condition cond) { |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1386 } | 1404 } |
| 1387 | 1405 |
| 1388 | 1406 |
| 1389 void Assembler::BranchLinkPatchable(const ExternalLabel* label) { | 1407 void Assembler::BranchLinkPatchable(const ExternalLabel* label) { |
| 1390 // Make sure that class CallPattern is able to patch the label referred | 1408 // Make sure that class CallPattern is able to patch the label referred |
| 1391 // to by this code sequence. | 1409 // to by this code sequence. |
| 1392 // For added code robustness, use 'blx lr' in a patchable sequence and | 1410 // For added code robustness, use 'blx lr' in a patchable sequence and |
| 1393 // use 'blx ip' in a non-patchable sequence (see other BranchLink flavors). | 1411 // use 'blx ip' in a non-patchable sequence (see other BranchLink flavors). |
| 1394 const int32_t offset = | 1412 const int32_t offset = |
| 1395 Array::data_offset() + 4*AddExternalLabel(label) - kHeapObjectTag; | 1413 Array::data_offset() + 4*AddExternalLabel(label) - kHeapObjectTag; |
| 1396 if (Address::CanHoldLoadOffset(kLoadWord, offset)) { | 1414 int32_t offset_mask; |
| 1415 if (Address::CanHoldLoadOffset(kLoadWord, offset, &offset_mask)) { | |
| 1397 ldr(LR, Address(PP, offset)); | 1416 ldr(LR, Address(PP, offset)); |
| 1398 } else { | 1417 } else { |
| 1399 int32_t offset12_hi = offset & ~kOffset12Mask; // signed | 1418 int32_t offset_hi = offset & ~offset_mask; // signed |
| 1400 uint32_t offset12_lo = offset & kOffset12Mask; // unsigned | 1419 uint32_t offset_lo = offset & offset_mask; // unsigned |
| 1401 // Inline a simplified version of AddImmediate(LR, CP, offset12_hi). | 1420 // Inline a simplified version of AddImmediate(LR, CP, offset_hi). |
| 1402 ShifterOperand shifter_op; | 1421 ShifterOperand shifter_op; |
| 1403 if (ShifterOperand::CanHold(offset12_hi, &shifter_op)) { | 1422 if (ShifterOperand::CanHold(offset_hi, &shifter_op)) { |
| 1404 add(LR, PP, shifter_op); | 1423 add(LR, PP, shifter_op); |
| 1405 } else { | 1424 } else { |
| 1406 movw(LR, Utils::Low16Bits(offset12_hi)); | 1425 movw(LR, Utils::Low16Bits(offset_hi)); |
| 1407 const uint16_t value_high = Utils::High16Bits(offset12_hi); | 1426 const uint16_t value_high = Utils::High16Bits(offset_hi); |
| 1408 if (value_high != 0) { | 1427 if (value_high != 0) { |
| 1409 movt(LR, value_high); | 1428 movt(LR, value_high); |
| 1410 } | 1429 } |
| 1411 add(LR, PP, ShifterOperand(LR)); | 1430 add(LR, PP, ShifterOperand(LR)); |
| 1412 } | 1431 } |
| 1413 ldr(LR, Address(LR, offset12_lo)); | 1432 ldr(LR, Address(LR, offset_lo)); |
| 1414 } | 1433 } |
| 1415 blx(LR); // Use blx instruction so that the return branch prediction works. | 1434 blx(LR); // Use blx instruction so that the return branch prediction works. |
| 1416 } | 1435 } |
| 1417 | 1436 |
| 1418 | 1437 |
| 1419 void Assembler::BranchLinkStore(const ExternalLabel* label, Address ad) { | 1438 void Assembler::BranchLinkStore(const ExternalLabel* label, Address ad) { |
| 1420 // TODO(regis): Revisit this code sequence. | 1439 // TODO(regis): Revisit this code sequence. |
| 1421 LoadImmediate(IP, label->address()); // Target address is never patched. | 1440 LoadImmediate(IP, label->address()); // Target address is never patched. |
| 1422 str(PC, ad); | 1441 str(PC, ad); |
| 1423 blx(IP); // Use blx instruction so that the return branch prediction works. | 1442 blx(IP); // Use blx instruction so that the return branch prediction works. |
| 1424 } | 1443 } |
| 1425 | 1444 |
| 1426 | 1445 |
| 1427 void Assembler::BranchLinkOffset(Register base, int offset) { | 1446 void Assembler::BranchLinkOffset(Register base, int offset) { |
| 1428 ASSERT(base != PC); | 1447 ASSERT(base != PC); |
| 1429 ASSERT(base != IP); | 1448 ASSERT(base != IP); |
| 1430 if (Address::CanHoldLoadOffset(kLoadWord, offset)) { | 1449 int32_t offset_mask; |
| 1450 if (Address::CanHoldLoadOffset(kLoadWord, offset, &offset_mask)) { | |
| 1431 ldr(IP, Address(base, offset)); | 1451 ldr(IP, Address(base, offset)); |
| 1432 } else { | 1452 } else { |
| 1433 int offset_hi = offset & ~kOffset12Mask; | 1453 int offset_hi = offset & ~offset_mask; |
| 1434 int offset_lo = offset & kOffset12Mask; | 1454 int offset_lo = offset & offset_mask; |
|
zra
2013/03/06 16:41:27
For consistency, you might put ASSERT(CanHoldLoadO
regis
2013/03/06 18:42:00
I am all for consistency. So I'll remove the extra
| |
| 1435 ShifterOperand offset_hi_op; | 1455 ShifterOperand offset_hi_op; |
| 1436 if (ShifterOperand::CanHold(offset_hi, &offset_hi_op)) { | 1456 if (ShifterOperand::CanHold(offset_hi, &offset_hi_op)) { |
| 1437 add(IP, base, offset_hi_op); | 1457 add(IP, base, offset_hi_op); |
| 1438 ldr(IP, Address(IP, offset_lo)); | 1458 ldr(IP, Address(IP, offset_lo)); |
| 1439 } else { | 1459 } else { |
| 1440 LoadImmediate(IP, offset_hi); | 1460 LoadImmediate(IP, offset_hi); |
| 1441 add(IP, IP, ShifterOperand(base)); | 1461 add(IP, IP, ShifterOperand(base)); |
| 1442 ldr(IP, Address(IP, offset_lo)); | 1462 ldr(IP, Address(IP, offset_lo)); |
| 1443 } | 1463 } |
| 1444 } | 1464 } |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1486 vmovdrr(dd, IP, scratch, cond); | 1506 vmovdrr(dd, IP, scratch, cond); |
| 1487 } | 1507 } |
| 1488 } | 1508 } |
| 1489 | 1509 |
| 1490 | 1510 |
| 1491 void Assembler::LoadFromOffset(LoadOperandType type, | 1511 void Assembler::LoadFromOffset(LoadOperandType type, |
| 1492 Register reg, | 1512 Register reg, |
| 1493 Register base, | 1513 Register base, |
| 1494 int32_t offset, | 1514 int32_t offset, |
| 1495 Condition cond) { | 1515 Condition cond) { |
| 1496 if (!Address::CanHoldLoadOffset(type, offset)) { | 1516 int32_t offset_mask; |
| 1517 if (!Address::CanHoldLoadOffset(type, offset, &offset_mask)) { | |
| 1497 ASSERT(base != IP); | 1518 ASSERT(base != IP); |
| 1498 LoadImmediate(IP, offset, cond); | 1519 AddImmediate(IP, base, offset & ~offset_mask, cond); |
| 1499 add(IP, IP, ShifterOperand(base), cond); | |
| 1500 base = IP; | 1520 base = IP; |
| 1501 offset = 0; | 1521 offset = offset & offset_mask; |
| 1502 } | 1522 } |
| 1503 ASSERT(Address::CanHoldLoadOffset(type, offset)); | 1523 ASSERT(Address::CanHoldLoadOffset(type, offset, &offset_mask)); |
| 1504 switch (type) { | 1524 switch (type) { |
| 1505 case kLoadSignedByte: | 1525 case kLoadSignedByte: |
| 1506 ldrsb(reg, Address(base, offset), cond); | 1526 ldrsb(reg, Address(base, offset), cond); |
| 1507 break; | 1527 break; |
| 1508 case kLoadUnsignedByte: | 1528 case kLoadUnsignedByte: |
| 1509 ldrb(reg, Address(base, offset), cond); | 1529 ldrb(reg, Address(base, offset), cond); |
| 1510 break; | 1530 break; |
| 1511 case kLoadSignedHalfword: | 1531 case kLoadSignedHalfword: |
| 1512 ldrsh(reg, Address(base, offset), cond); | 1532 ldrsh(reg, Address(base, offset), cond); |
| 1513 break; | 1533 break; |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 1524 UNREACHABLE(); | 1544 UNREACHABLE(); |
| 1525 } | 1545 } |
| 1526 } | 1546 } |
| 1527 | 1547 |
| 1528 | 1548 |
| 1529 void Assembler::StoreToOffset(StoreOperandType type, | 1549 void Assembler::StoreToOffset(StoreOperandType type, |
| 1530 Register reg, | 1550 Register reg, |
| 1531 Register base, | 1551 Register base, |
| 1532 int32_t offset, | 1552 int32_t offset, |
| 1533 Condition cond) { | 1553 Condition cond) { |
| 1534 if (!Address::CanHoldStoreOffset(type, offset)) { | 1554 int32_t offset_mask; |
| 1555 if (!Address::CanHoldStoreOffset(type, offset, &offset_mask)) { | |
| 1535 ASSERT(reg != IP); | 1556 ASSERT(reg != IP); |
| 1536 ASSERT(base != IP); | 1557 ASSERT(base != IP); |
| 1537 LoadImmediate(IP, offset, cond); | 1558 AddImmediate(IP, base, offset & ~offset_mask, cond); |
| 1538 add(IP, IP, ShifterOperand(base), cond); | |
| 1539 base = IP; | 1559 base = IP; |
| 1540 offset = 0; | 1560 offset = offset & offset_mask; |
| 1541 } | 1561 } |
| 1542 ASSERT(Address::CanHoldStoreOffset(type, offset)); | 1562 ASSERT(Address::CanHoldStoreOffset(type, offset, &offset_mask)); |
| 1543 switch (type) { | 1563 switch (type) { |
| 1544 case kStoreByte: | 1564 case kStoreByte: |
| 1545 strb(reg, Address(base, offset), cond); | 1565 strb(reg, Address(base, offset), cond); |
| 1546 break; | 1566 break; |
| 1547 case kStoreHalfword: | 1567 case kStoreHalfword: |
| 1548 strh(reg, Address(base, offset), cond); | 1568 strh(reg, Address(base, offset), cond); |
| 1549 break; | 1569 break; |
| 1550 case kStoreWord: | 1570 case kStoreWord: |
| 1551 str(reg, Address(base, offset), cond); | 1571 str(reg, Address(base, offset), cond); |
| 1552 break; | 1572 break; |
| 1553 case kStoreWordPair: | 1573 case kStoreWordPair: |
| 1554 strd(reg, Address(base, offset), cond); | 1574 strd(reg, Address(base, offset), cond); |
| 1555 break; | 1575 break; |
| 1556 default: | 1576 default: |
| 1557 UNREACHABLE(); | 1577 UNREACHABLE(); |
| 1558 } | 1578 } |
| 1559 } | 1579 } |
| 1560 | 1580 |
| 1561 | 1581 |
| 1562 void Assembler::LoadSFromOffset(SRegister reg, | 1582 void Assembler::LoadSFromOffset(SRegister reg, |
| 1563 Register base, | 1583 Register base, |
| 1564 int32_t offset, | 1584 int32_t offset, |
| 1565 Condition cond) { | 1585 Condition cond) { |
| 1566 if (!Address::CanHoldLoadOffset(kLoadSWord, offset)) { | 1586 int32_t offset_mask; |
| 1587 if (!Address::CanHoldLoadOffset(kLoadSWord, offset, &offset_mask)) { | |
| 1567 ASSERT(base != IP); | 1588 ASSERT(base != IP); |
| 1568 LoadImmediate(IP, offset, cond); | 1589 AddImmediate(IP, base, offset & ~offset_mask, cond); |
| 1569 add(IP, IP, ShifterOperand(base), cond); | |
| 1570 base = IP; | 1590 base = IP; |
| 1571 offset = 0; | 1591 offset = offset & offset_mask; |
| 1572 } | 1592 } |
| 1573 ASSERT(Address::CanHoldLoadOffset(kLoadSWord, offset)); | 1593 ASSERT(Address::CanHoldLoadOffset(kLoadSWord, offset, &offset_mask)); |
| 1574 vldrs(reg, Address(base, offset), cond); | 1594 vldrs(reg, Address(base, offset), cond); |
| 1575 } | 1595 } |
| 1576 | 1596 |
| 1577 | 1597 |
| 1578 void Assembler::StoreSToOffset(SRegister reg, | 1598 void Assembler::StoreSToOffset(SRegister reg, |
| 1579 Register base, | 1599 Register base, |
| 1580 int32_t offset, | 1600 int32_t offset, |
| 1581 Condition cond) { | 1601 Condition cond) { |
| 1582 if (!Address::CanHoldStoreOffset(kStoreSWord, offset)) { | 1602 int32_t offset_mask; |
| 1603 if (!Address::CanHoldStoreOffset(kStoreSWord, offset, &offset_mask)) { | |
| 1583 ASSERT(base != IP); | 1604 ASSERT(base != IP); |
| 1584 LoadImmediate(IP, offset, cond); | 1605 AddImmediate(IP, base, offset & ~offset_mask, cond); |
| 1585 add(IP, IP, ShifterOperand(base), cond); | |
| 1586 base = IP; | 1606 base = IP; |
| 1587 offset = 0; | 1607 offset = offset & offset_mask; |
| 1588 } | 1608 } |
| 1589 ASSERT(Address::CanHoldStoreOffset(kStoreSWord, offset)); | 1609 ASSERT(Address::CanHoldStoreOffset(kStoreSWord, offset, &offset_mask)); |
| 1590 vstrs(reg, Address(base, offset), cond); | 1610 vstrs(reg, Address(base, offset), cond); |
| 1591 } | 1611 } |
| 1592 | 1612 |
| 1593 | 1613 |
| 1594 void Assembler::LoadDFromOffset(DRegister reg, | 1614 void Assembler::LoadDFromOffset(DRegister reg, |
| 1595 Register base, | 1615 Register base, |
| 1596 int32_t offset, | 1616 int32_t offset, |
| 1597 Condition cond) { | 1617 Condition cond) { |
| 1598 if (!Address::CanHoldLoadOffset(kLoadDWord, offset)) { | 1618 int32_t offset_mask; |
| 1619 if (!Address::CanHoldLoadOffset(kLoadDWord, offset, &offset_mask)) { | |
| 1599 ASSERT(base != IP); | 1620 ASSERT(base != IP); |
| 1600 LoadImmediate(IP, offset, cond); | 1621 AddImmediate(IP, base, offset & ~offset_mask, cond); |
| 1601 add(IP, IP, ShifterOperand(base), cond); | |
| 1602 base = IP; | 1622 base = IP; |
| 1603 offset = 0; | 1623 offset = offset & offset_mask; |
| 1604 } | 1624 } |
| 1605 ASSERT(Address::CanHoldLoadOffset(kLoadDWord, offset)); | 1625 ASSERT(Address::CanHoldLoadOffset(kLoadDWord, offset, &offset_mask)); |
| 1606 vldrd(reg, Address(base, offset), cond); | 1626 vldrd(reg, Address(base, offset), cond); |
| 1607 } | 1627 } |
| 1608 | 1628 |
| 1609 | 1629 |
| 1610 void Assembler::StoreDToOffset(DRegister reg, | 1630 void Assembler::StoreDToOffset(DRegister reg, |
| 1611 Register base, | 1631 Register base, |
| 1612 int32_t offset, | 1632 int32_t offset, |
| 1613 Condition cond) { | 1633 Condition cond) { |
| 1614 if (!Address::CanHoldStoreOffset(kStoreDWord, offset)) { | 1634 int32_t offset_mask; |
| 1635 if (!Address::CanHoldStoreOffset(kStoreDWord, offset, &offset_mask)) { | |
| 1615 ASSERT(base != IP); | 1636 ASSERT(base != IP); |
| 1616 LoadImmediate(IP, offset, cond); | 1637 AddImmediate(IP, base, offset & ~offset_mask, cond); |
| 1617 add(IP, IP, ShifterOperand(base), cond); | |
| 1618 base = IP; | 1638 base = IP; |
| 1619 offset = 0; | 1639 offset = offset & offset_mask; |
| 1620 } | 1640 } |
| 1621 ASSERT(Address::CanHoldStoreOffset(kStoreDWord, offset)); | 1641 ASSERT(Address::CanHoldStoreOffset(kStoreDWord, offset, &offset_mask)); |
| 1622 vstrd(reg, Address(base, offset), cond); | 1642 vstrd(reg, Address(base, offset), cond); |
| 1623 } | 1643 } |
| 1624 | 1644 |
| 1625 | 1645 |
| 1626 void Assembler::AddImmediate(Register rd, int32_t value, Condition cond) { | 1646 void Assembler::AddImmediate(Register rd, int32_t value, Condition cond) { |
| 1627 AddImmediate(rd, rd, value, cond); | 1647 AddImmediate(rd, rd, value, cond); |
| 1628 } | 1648 } |
| 1629 | 1649 |
| 1630 | 1650 |
| 1631 void Assembler::AddImmediate(Register rd, Register rn, int32_t value, | 1651 void Assembler::AddImmediate(Register rd, Register rn, int32_t value, |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1777 bic(SP, SP, ShifterOperand(OS::ActivationFrameAlignment() - 1)); | 1797 bic(SP, SP, ShifterOperand(OS::ActivationFrameAlignment() - 1)); |
| 1778 } | 1798 } |
| 1779 } | 1799 } |
| 1780 | 1800 |
| 1781 | 1801 |
| 1782 void Assembler::EnterCallRuntimeFrame(intptr_t frame_space) { | 1802 void Assembler::EnterCallRuntimeFrame(intptr_t frame_space) { |
| 1783 // Preserve volatile CPU registers. | 1803 // Preserve volatile CPU registers. |
| 1784 EnterFrame(kDartVolatileCpuRegs | (1 << FP), 0); | 1804 EnterFrame(kDartVolatileCpuRegs | (1 << FP), 0); |
| 1785 | 1805 |
| 1786 // Preserve all volatile FPU registers. | 1806 // Preserve all volatile FPU registers. |
| 1787 // TODO(regis): Use vstmd instruction once supported. | 1807 vstmd(DB_W, SP, kDartFirstVolatileFpuReg, kDartLastVolatileFpuReg); |
| 1788 // vstmd(DB_W, SP, kDartFirstVolatileFpuReg, kDartLastVolatileFpuReg); | |
| 1789 | 1808 |
| 1790 ReserveAlignedFrameSpace(frame_space); | 1809 ReserveAlignedFrameSpace(frame_space); |
| 1791 } | 1810 } |
| 1792 | 1811 |
| 1793 | 1812 |
| 1794 void Assembler::LeaveCallRuntimeFrame() { | 1813 void Assembler::LeaveCallRuntimeFrame() { |
| 1795 // SP might have been modified to reserve space for arguments | 1814 // SP might have been modified to reserve space for arguments |
| 1796 // and ensure proper alignment of the stack frame. | 1815 // and ensure proper alignment of the stack frame. |
| 1797 // We need to restore it before restoring registers. | 1816 // We need to restore it before restoring registers. |
| 1798 const intptr_t kPushedRegistersSize = | 1817 const intptr_t kPushedRegistersSize = |
| 1799 kDartVolatileCpuRegCount * kWordSize; | 1818 kDartVolatileCpuRegCount * kWordSize + |
| 1800 // TODO(regis): + kDartVolatileFpuRegCount * 2 * kWordSize; | 1819 kDartVolatileFpuRegCount * 2 * kWordSize; |
| 1801 AddImmediate(SP, FP, -kPushedRegistersSize); | 1820 AddImmediate(SP, FP, -kPushedRegistersSize); |
| 1802 | 1821 |
| 1803 // Restore all volatile FPU registers. | 1822 // Restore all volatile FPU registers. |
| 1804 // TODO(regis): Use vldmd instruction once supported. | 1823 vldmd(IA_W, SP, kDartFirstVolatileFpuReg, kDartLastVolatileFpuReg); |
| 1805 // vldmd(IA_W, SP, kDartFirstVolatileFpuReg, kDartLastVolatileFpuReg); | |
| 1806 | 1824 |
| 1807 // Restore volatile CPU registers. | 1825 // Restore volatile CPU registers. |
| 1808 LeaveFrame(kDartVolatileCpuRegs | (1 << FP)); | 1826 LeaveFrame(kDartVolatileCpuRegs | (1 << FP)); |
| 1809 } | 1827 } |
| 1810 | 1828 |
| 1811 | 1829 |
| 1812 void Assembler::CallRuntime(const RuntimeEntry& entry) { | 1830 void Assembler::CallRuntime(const RuntimeEntry& entry) { |
| 1813 entry.Call(this); | 1831 entry.Call(this); |
| 1814 } | 1832 } |
| 1815 | 1833 |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1936 // Do not reuse an existing entry, since each reference may be patched | 1954 // Do not reuse an existing entry, since each reference may be patched |
| 1937 // independently. | 1955 // independently. |
| 1938 object_pool_.Add(smi); | 1956 object_pool_.Add(smi); |
| 1939 return object_pool_.Length() - 1; | 1957 return object_pool_.Length() - 1; |
| 1940 } | 1958 } |
| 1941 | 1959 |
| 1942 } // namespace dart | 1960 } // namespace dart |
| 1943 | 1961 |
| 1944 #endif // defined TARGET_ARCH_ARM | 1962 #endif // defined TARGET_ARCH_ARM |
| 1945 | 1963 |
| OLD | NEW |