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

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