Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(181)

Side by Side Diff: runtime/vm/assembler_arm.cc

Issue 12481007: Clean up ARM assembly code loading and storing from/to a large offset. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/assembler_arm.h ('k') | runtime/vm/stub_code_arm.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/assembler_arm.h ('k') | runtime/vm/stub_code_arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698