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

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

Powered by Google App Engine
This is Rietveld 408576698