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

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

Issue 12335102: Compile and simulate first dart function on arm generated from ast. (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
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 9
10 #include "vm/stub_code.h" 10 #include "vm/stub_code.h"
(...skipping 972 matching lines...) Expand 10 before | Expand all | Expand 10 after
983 void Assembler::vmstat(Condition cond) { // VMRS APSR_nzcv, FPSCR 983 void Assembler::vmstat(Condition cond) { // VMRS APSR_nzcv, FPSCR
984 ASSERT(cond != kNoCondition); 984 ASSERT(cond != kNoCondition);
985 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 985 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
986 B27 | B26 | B25 | B23 | B22 | B21 | B20 | B16 | 986 B27 | B26 | B25 | B23 | B22 | B21 | B20 | B16 |
987 (static_cast<int32_t>(PC)*B12) | 987 (static_cast<int32_t>(PC)*B12) |
988 B11 | B9 | B4; 988 B11 | B9 | B4;
989 Emit(encoding); 989 Emit(encoding);
990 } 990 }
991 991
992 992
993 void Assembler::svc(uint32_t imm24) { 993 void Assembler::svc(uint32_t imm24, Condition cond) {
994 ASSERT(cond != kNoCondition);
994 ASSERT(imm24 < (1 << 24)); 995 ASSERT(imm24 < (1 << 24));
995 int32_t encoding = (AL << kConditionShift) | B27 | B26 | B25 | B24 | imm24; 996 int32_t encoding = (cond << kConditionShift) | B27 | B26 | B25 | B24 | imm24;
996 Emit(encoding); 997 Emit(encoding);
997 } 998 }
998 999
999 1000
1000 void Assembler::bkpt(uint16_t imm16) { 1001 void Assembler::bkpt(uint16_t imm16, Condition cond) {
1001 int32_t encoding = (AL << kConditionShift) | B24 | B21 | 1002 ASSERT(cond != kNoCondition);
1003 int32_t encoding = (cond << kConditionShift) | B24 | B21 |
1002 ((imm16 >> 4) << 8) | B6 | B5 | B4 | (imm16 & 0xf); 1004 ((imm16 >> 4) << 8) | B6 | B5 | B4 | (imm16 & 0xf);
1003 Emit(encoding); 1005 Emit(encoding);
1004 } 1006 }
1005 1007
1006 1008
1007 void Assembler::b(Label* label, Condition cond) { 1009 void Assembler::b(Label* label, Condition cond) {
1008 EmitBranch(cond, label, false); 1010 EmitBranch(cond, label, false);
1009 } 1011 }
1010 1012
1011 1013
1012 void Assembler::bl(Label* label, Condition cond) { 1014 void Assembler::bl(Label* label, Condition cond) {
1013 EmitBranch(cond, label, true); 1015 EmitBranch(cond, label, true);
1014 } 1016 }
1015 1017
1016 1018
1019 void Assembler::bx(Register rm, Condition cond) {
1020 ASSERT(rm != kNoRegister);
1021 ASSERT(cond != kNoCondition);
1022 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1023 B24 | B21 | (0xfff << 8) | B4 |
1024 (static_cast<int32_t>(rm) << kRmShift);
1025 Emit(encoding);
1026 }
1027
1028
1017 void Assembler::blx(Register rm, Condition cond) { 1029 void Assembler::blx(Register rm, Condition cond) {
1018 ASSERT(rm != kNoRegister); 1030 ASSERT(rm != kNoRegister);
1019 ASSERT(cond != kNoCondition); 1031 ASSERT(cond != kNoCondition);
1020 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1032 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
1021 B24 | B21 | (0xfff << 8) | B5 | B4 | 1033 B24 | B21 | (0xfff << 8) | B5 | B4 |
1022 (static_cast<int32_t>(rm) << kRmShift); 1034 (static_cast<int32_t>(rm) << kRmShift);
1023 Emit(encoding); 1035 Emit(encoding);
1024 } 1036 }
1025 1037
1026 1038
1027 void Assembler::MarkExceptionHandler(Label* label) { 1039 void Assembler::MarkExceptionHandler(Label* label) {
1028 EmitType01(AL, 1, TST, 1, PC, R0, ShifterOperand(0)); 1040 EmitType01(AL, 1, TST, 1, PC, R0, ShifterOperand(0));
1029 Label l; 1041 Label l;
1030 b(&l); 1042 b(&l);
1031 EmitBranch(AL, label, false); 1043 EmitBranch(AL, label, false);
1032 Bind(&l); 1044 Bind(&l);
1033 } 1045 }
1034 1046
1035 1047
1036 void Assembler::LoadObject(Register rd, const Object& object) { 1048 void Assembler::LoadObject(Register rd, const Object& object) {
1037 // TODO(regis): If the object is never relocated (null, true, false, ...), 1049 if (object.IsNull() ||
1038 // load as immediate. 1050 object.IsSmi() ||
1051 (object.raw() == Bool::True().raw()) ||
1052 (object.raw() == Bool::False().raw())) {
1053 // This object is never relocated; do not use object pool.
1054 LoadImmediate(rd, reinterpret_cast<int32_t>(object.raw()));
1055 return;
1056 }
1039 const int32_t offset = 1057 const int32_t offset =
1040 Array::data_offset() + 4*AddObject(object) - kHeapObjectTag; 1058 Array::data_offset() + 4*AddObject(object) - kHeapObjectTag;
1041 if (Address::CanHoldLoadOffset(kLoadWord, offset)) { 1059 if (Address::CanHoldLoadOffset(kLoadWord, offset)) {
1042 ldr(rd, Address(PP, offset)); 1060 ldr(rd, Address(PP, offset));
1043 } else { 1061 } else {
1044 int32_t offset12_hi = offset & ~kOffset12Mask; // signed 1062 int32_t offset12_hi = offset & ~kOffset12Mask; // signed
1045 uint32_t offset12_lo = offset & kOffset12Mask; // unsigned 1063 uint32_t offset12_lo = offset & kOffset12Mask; // unsigned
1046 AddConstant(rd, PP, offset12_hi); 1064 AddImmediate(rd, PP, offset12_hi);
1047 ldr(rd, Address(rd, offset12_lo)); 1065 ldr(rd, Address(rd, offset12_lo));
1048 } 1066 }
1049 } 1067 }
1050 1068
1051 1069
1052 void Assembler::Bind(Label* label) { 1070 void Assembler::Bind(Label* label) {
1053 ASSERT(!label->IsBound()); 1071 ASSERT(!label->IsBound());
1054 int bound_pc = buffer_.Size(); 1072 int bound_pc = buffer_.Size();
1055 while (label->IsLinked()) { 1073 while (label->IsLinked()) {
1056 int32_t position = label->Position(); 1074 int32_t position = label->Position();
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
1156 ASSERT(shift_imm != 0); // Use Rrx instruction. 1174 ASSERT(shift_imm != 0); // Use Rrx instruction.
1157 mov(rd, ShifterOperand(rm, ROR, shift_imm), cond); 1175 mov(rd, ShifterOperand(rm, ROR, shift_imm), cond);
1158 } 1176 }
1159 1177
1160 1178
1161 void Assembler::Rrx(Register rd, Register rm, Condition cond) { 1179 void Assembler::Rrx(Register rd, Register rm, Condition cond) {
1162 mov(rd, ShifterOperand(rm, ROR, 0), cond); 1180 mov(rd, ShifterOperand(rm, ROR, 0), cond);
1163 } 1181 }
1164 1182
1165 1183
1166 void Assembler::Branch(const ExternalLabel* label) { 1184 void Assembler::Branch(const ExternalLabel* label, Condition cond) {
1167 LoadImmediate(IP, label->address()); // Target address is never patched. 1185 LoadImmediate(IP, label->address(), cond); // Address is never patched.
1168 mov(PC, ShifterOperand(IP)); 1186 mov(PC, ShifterOperand(IP), cond);
1169 } 1187 }
1170 1188
1171 1189
1172 void Assembler::BranchLink(const ExternalLabel* label) { 1190 void Assembler::BranchLink(const ExternalLabel* label) {
1173 LoadImmediate(IP, label->address()); // Target address is never patched. 1191 LoadImmediate(IP, label->address()); // Target address is never patched.
1174 blx(IP); // Use blx instruction so that the return branch prediction works. 1192 blx(IP); // Use blx instruction so that the return branch prediction works.
1175 } 1193 }
1176 1194
1177 1195
1178 void Assembler::BranchLinkPatchable(const ExternalLabel* label) { 1196 void Assembler::BranchLinkPatchable(const ExternalLabel* label) {
1179 // Make sure that class CallPattern is able to patch the label referred 1197 // Make sure that class CallPattern is able to patch the label referred
1180 // to by this code sequence. 1198 // to by this code sequence.
1181 // For added code robustness, use 'blx lr' in a patchable sequence and 1199 // For added code robustness, use 'blx lr' in a patchable sequence and
1182 // use 'blx ip' in a non-patchable sequence (see other BranchLink flavors). 1200 // use 'blx ip' in a non-patchable sequence (see other BranchLink flavors).
1183 const int32_t offset = 1201 const int32_t offset =
1184 Array::data_offset() + 4*AddExternalLabel(label) - kHeapObjectTag; 1202 Array::data_offset() + 4*AddExternalLabel(label) - kHeapObjectTag;
1185 if (Address::CanHoldLoadOffset(kLoadWord, offset)) { 1203 if (Address::CanHoldLoadOffset(kLoadWord, offset)) {
1186 ldr(LR, Address(PP, offset)); 1204 ldr(LR, Address(PP, offset));
1187 } else { 1205 } else {
1188 int32_t offset12_hi = offset & ~kOffset12Mask; // signed 1206 int32_t offset12_hi = offset & ~kOffset12Mask; // signed
1189 uint32_t offset12_lo = offset & kOffset12Mask; // unsigned 1207 uint32_t offset12_lo = offset & kOffset12Mask; // unsigned
1190 // Inline a simplified version of AddConstant(LR, CP, offset12_hi). 1208 // Inline a simplified version of AddImmediate(LR, CP, offset12_hi).
1191 ShifterOperand shifter_op; 1209 ShifterOperand shifter_op;
1192 if (ShifterOperand::CanHold(offset12_hi, &shifter_op)) { 1210 if (ShifterOperand::CanHold(offset12_hi, &shifter_op)) {
1193 add(LR, PP, shifter_op); 1211 add(LR, PP, shifter_op);
1194 } else { 1212 } else {
1195 movw(LR, Utils::Low16Bits(offset12_hi)); 1213 movw(LR, Utils::Low16Bits(offset12_hi));
1196 const uint16_t value_high = Utils::High16Bits(offset12_hi); 1214 const uint16_t value_high = Utils::High16Bits(offset12_hi);
1197 if (value_high != 0) { 1215 if (value_high != 0) {
1198 movt(LR, value_high); 1216 movt(LR, value_high);
1199 } 1217 }
1200 add(LR, PP, ShifterOperand(LR)); 1218 add(LR, PP, ShifterOperand(LR));
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
1405 LoadImmediate(IP, offset, cond); 1423 LoadImmediate(IP, offset, cond);
1406 add(IP, IP, ShifterOperand(base), cond); 1424 add(IP, IP, ShifterOperand(base), cond);
1407 base = IP; 1425 base = IP;
1408 offset = 0; 1426 offset = 0;
1409 } 1427 }
1410 ASSERT(Address::CanHoldStoreOffset(kStoreDWord, offset)); 1428 ASSERT(Address::CanHoldStoreOffset(kStoreDWord, offset));
1411 vstrd(reg, Address(base, offset), cond); 1429 vstrd(reg, Address(base, offset), cond);
1412 } 1430 }
1413 1431
1414 1432
1415 void Assembler::AddConstant(Register rd, int32_t value, Condition cond) { 1433 void Assembler::AddImmediate(Register rd, int32_t value, Condition cond) {
1416 AddConstant(rd, rd, value, cond); 1434 AddImmediate(rd, rd, value, cond);
1417 } 1435 }
1418 1436
1419 1437
1420 void Assembler::AddConstant(Register rd, Register rn, int32_t value, 1438 void Assembler::AddImmediate(Register rd, Register rn, int32_t value,
1421 Condition cond) { 1439 Condition cond) {
1422 if (value == 0) { 1440 if (value == 0) {
1423 if (rd != rn) { 1441 if (rd != rn) {
1424 mov(rd, ShifterOperand(rn), cond); 1442 mov(rd, ShifterOperand(rn), cond);
1425 } 1443 }
1426 return; 1444 return;
1427 } 1445 }
1428 // We prefer to select the shorter code sequence rather than selecting add for 1446 // We prefer to select the shorter code sequence rather than selecting add for
1429 // positive values and sub for negatives ones, which would slightly improve 1447 // positive values and sub for negatives ones, which would slightly improve
1430 // the readability of generated code for some constants. 1448 // the readability of generated code for some constants.
(...skipping 15 matching lines...) Expand all
1446 uint16_t value_high = Utils::High16Bits(value); 1464 uint16_t value_high = Utils::High16Bits(value);
1447 if (value_high != 0) { 1465 if (value_high != 0) {
1448 movt(IP, value_high, cond); 1466 movt(IP, value_high, cond);
1449 } 1467 }
1450 add(rd, rn, ShifterOperand(IP), cond); 1468 add(rd, rn, ShifterOperand(IP), cond);
1451 } 1469 }
1452 } 1470 }
1453 } 1471 }
1454 1472
1455 1473
1456 void Assembler::AddConstantSetFlags(Register rd, Register rn, int32_t value, 1474 void Assembler::AddImmediateSetFlags(Register rd, Register rn, int32_t value,
1457 Condition cond) { 1475 Condition cond) {
1458 ShifterOperand shifter_op; 1476 ShifterOperand shifter_op;
1459 if (ShifterOperand::CanHold(value, &shifter_op)) { 1477 if (ShifterOperand::CanHold(value, &shifter_op)) {
1460 adds(rd, rn, shifter_op, cond); 1478 adds(rd, rn, shifter_op, cond);
1461 } else if (ShifterOperand::CanHold(-value, &shifter_op)) { 1479 } else if (ShifterOperand::CanHold(-value, &shifter_op)) {
1462 subs(rd, rn, shifter_op, cond); 1480 subs(rd, rn, shifter_op, cond);
1463 } else { 1481 } else {
1464 ASSERT(rn != IP); 1482 ASSERT(rn != IP);
1465 if (ShifterOperand::CanHold(~value, &shifter_op)) { 1483 if (ShifterOperand::CanHold(~value, &shifter_op)) {
1466 mvn(IP, shifter_op, cond); 1484 mvn(IP, shifter_op, cond);
1467 adds(rd, rn, ShifterOperand(IP), cond); 1485 adds(rd, rn, ShifterOperand(IP), cond);
1468 } else if (ShifterOperand::CanHold(~(-value), &shifter_op)) { 1486 } else if (ShifterOperand::CanHold(~(-value), &shifter_op)) {
1469 mvn(IP, shifter_op, cond); 1487 mvn(IP, shifter_op, cond);
1470 subs(rd, rn, ShifterOperand(IP), cond); 1488 subs(rd, rn, ShifterOperand(IP), cond);
1471 } else { 1489 } else {
1472 movw(IP, Utils::Low16Bits(value), cond); 1490 movw(IP, Utils::Low16Bits(value), cond);
1473 uint16_t value_high = Utils::High16Bits(value); 1491 uint16_t value_high = Utils::High16Bits(value);
1474 if (value_high != 0) { 1492 if (value_high != 0) {
1475 movt(IP, value_high, cond); 1493 movt(IP, value_high, cond);
1476 } 1494 }
1477 adds(rd, rn, ShifterOperand(IP), cond); 1495 adds(rd, rn, ShifterOperand(IP), cond);
1478 } 1496 }
1479 } 1497 }
1480 } 1498 }
1481 1499
1482 1500
1483 void Assembler::AddConstantWithCarry(Register rd, Register rn, int32_t value, 1501 void Assembler::AddImmediateWithCarry(Register rd, Register rn, int32_t value,
1484 Condition cond) { 1502 Condition cond) {
1485 ShifterOperand shifter_op; 1503 ShifterOperand shifter_op;
1486 if (ShifterOperand::CanHold(value, &shifter_op)) { 1504 if (ShifterOperand::CanHold(value, &shifter_op)) {
1487 adc(rd, rn, shifter_op, cond); 1505 adc(rd, rn, shifter_op, cond);
1488 } else if (ShifterOperand::CanHold(-value - 1, &shifter_op)) { 1506 } else if (ShifterOperand::CanHold(-value - 1, &shifter_op)) {
1489 sbc(rd, rn, shifter_op, cond); 1507 sbc(rd, rn, shifter_op, cond);
1490 } else { 1508 } else {
1491 ASSERT(rn != IP); 1509 ASSERT(rn != IP);
1492 if (ShifterOperand::CanHold(~value, &shifter_op)) { 1510 if (ShifterOperand::CanHold(~value, &shifter_op)) {
1493 mvn(IP, shifter_op, cond); 1511 mvn(IP, shifter_op, cond);
1494 adc(rd, rn, ShifterOperand(IP), cond); 1512 adc(rd, rn, ShifterOperand(IP), cond);
1495 } else if (ShifterOperand::CanHold(~(-value - 1), &shifter_op)) { 1513 } else if (ShifterOperand::CanHold(~(-value - 1), &shifter_op)) {
1496 mvn(IP, shifter_op, cond); 1514 mvn(IP, shifter_op, cond);
1497 sbc(rd, rn, ShifterOperand(IP), cond); 1515 sbc(rd, rn, ShifterOperand(IP), cond);
1498 } else { 1516 } else {
1499 movw(IP, Utils::Low16Bits(value), cond); 1517 movw(IP, Utils::Low16Bits(value), cond);
1500 uint16_t value_high = Utils::High16Bits(value); 1518 uint16_t value_high = Utils::High16Bits(value);
1501 if (value_high != 0) { 1519 if (value_high != 0) {
1502 movt(IP, value_high, cond); 1520 movt(IP, value_high, cond);
1503 } 1521 }
1504 adc(rd, rn, ShifterOperand(IP), cond); 1522 adc(rd, rn, ShifterOperand(IP), cond);
1505 } 1523 }
1506 } 1524 }
1507 } 1525 }
1508 1526
1509 1527
1528 void Assembler::CompareImmediate(Register rn, int32_t value, Condition cond) {
1529 ShifterOperand shifter_op;
1530 if (ShifterOperand::CanHold(value, &shifter_op)) {
1531 cmp(rn, shifter_op, cond);
1532 } else {
1533 ASSERT(rn != IP);
1534 LoadImmediate(IP, cond);
1535 cmp(rn, ShifterOperand(IP), cond);
1536 }
1537 }
1538
1539
1540 static int NumRegsBelowFP(RegList regs) {
1541 int count = 0;
1542 for (int i = 0; i < FP; i++) {
1543 if ((regs & (1 << i)) != 0) {
1544 count++;
1545 }
1546 }
1547 return count;
1548 }
1549
1550
1551 void Assembler::EnterFrame(RegList regs, intptr_t frame_size) {
1552 if (prologue_offset_ == -1) {
1553 prologue_offset_ = CodeSize();
1554 }
1555 PushList(regs);
1556 if ((regs & (1 << FP)) != 0) {
1557 // Set FP to the saved previous FP.
1558 add(FP, SP, ShifterOperand(4 * NumRegsBelowFP(regs)));
1559 }
1560 AddImmediate(SP, -frame_size);
1561 }
1562
1563
1564 void Assembler::LeaveFrame(RegList regs) {
1565 ASSERT((regs & (1 << PC)) == 0); // Must not pop PC.
1566 if ((regs & (1 << FP)) != 0) {
1567 // Use FP to set SP.
1568 sub(SP, FP, ShifterOperand(4 * NumRegsBelowFP(regs)));
1569 }
1570 PopList(regs);
1571 }
1572
1573
1574 void Assembler::Ret() {
1575 bx(LR);
1576 }
1577
1578
1579 void Assembler::ReserveAlignedFrameSpace(intptr_t frame_space) {
1580 // Reserve space for arguments and align frame before entering
1581 // the C++ world.
1582 AddImmediate(SP, -frame_space);
1583 if (OS::ActivationFrameAlignment() > 0) {
1584 and_(SP, SP, ShifterOperand(~(OS::ActivationFrameAlignment() - 1)));
1585 }
1586 }
1587
1588
1510 void Assembler::Stop(const char* message) { 1589 void Assembler::Stop(const char* message) {
1511 if (FLAG_print_stop_message) { 1590 if (FLAG_print_stop_message) {
1512 PushList((1 << R0) | (1 << IP) | (1 << LR)); // Preserve R0, IP, LR. 1591 PushList((1 << R0) | (1 << IP) | (1 << LR)); // Preserve R0, IP, LR.
1513 LoadImmediate(R0, reinterpret_cast<int32_t>(message)); 1592 LoadImmediate(R0, reinterpret_cast<int32_t>(message));
1514 // PrintStopMessage() preserves all registers. 1593 // PrintStopMessage() preserves all registers.
1515 BranchLink(&StubCode::PrintStopMessageLabel()); // Passing message in R0. 1594 BranchLink(&StubCode::PrintStopMessageLabel()); // Passing message in R0.
1516 PopList((1 << R0) | (1 << IP) | (1 << LR)); // Restore R0, IP, LR. 1595 PopList((1 << R0) | (1 << IP) | (1 << LR)); // Restore R0, IP, LR.
1517 } 1596 }
1518 // Emit the message address before the svc instruction, so that we can 1597 // Emit the message address before the svc instruction, so that we can
1519 // 'unstop' and continue execution in the simulator or jump to the next 1598 // 'unstop' and continue execution in the simulator or jump to the next
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1574 // Do not reuse an existing entry, since each reference may be patched 1653 // Do not reuse an existing entry, since each reference may be patched
1575 // independently. 1654 // independently.
1576 object_pool_.Add(smi); 1655 object_pool_.Add(smi);
1577 return object_pool_.Length() - 1; 1656 return object_pool_.Length() - 1;
1578 } 1657 }
1579 1658
1580 } // namespace dart 1659 } // namespace dart
1581 1660
1582 #endif // defined TARGET_ARCH_ARM 1661 #endif // defined TARGET_ARCH_ARM
1583 1662
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698