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" // Needed here to get TARGET_ARCH_ARM. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. |
6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
7 | 7 |
8 #include "vm/flow_graph_compiler.h" | 8 #include "vm/flow_graph_compiler.h" |
9 | 9 |
10 #include "lib/error.h" | 10 #include "lib/error.h" |
(...skipping 1485 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1496 | 1496 |
1497 void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) { | 1497 void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) { |
1498 // TODO(vegorov): consider saving only caller save (volatile) registers. | 1498 // TODO(vegorov): consider saving only caller save (volatile) registers. |
1499 const intptr_t fpu_regs_count = locs->live_registers()->fpu_regs_count(); | 1499 const intptr_t fpu_regs_count = locs->live_registers()->fpu_regs_count(); |
1500 if (fpu_regs_count > 0) { | 1500 if (fpu_regs_count > 0) { |
1501 __ AddImmediate(SP, -(fpu_regs_count * kFpuRegisterSize)); | 1501 __ AddImmediate(SP, -(fpu_regs_count * kFpuRegisterSize)); |
1502 // Store fpu registers with the lowest register number at the lowest | 1502 // Store fpu registers with the lowest register number at the lowest |
1503 // address. | 1503 // address. |
1504 intptr_t offset = 0; | 1504 intptr_t offset = 0; |
1505 for (intptr_t reg_idx = 0; reg_idx < kNumberOfFpuRegisters; ++reg_idx) { | 1505 for (intptr_t reg_idx = 0; reg_idx < kNumberOfFpuRegisters; ++reg_idx) { |
1506 DRegister fpu_reg = static_cast<DRegister>(reg_idx); | 1506 QRegister fpu_reg = static_cast<QRegister>(reg_idx); |
1507 if (locs->live_registers()->ContainsFpuRegister(fpu_reg)) { | 1507 if (locs->live_registers()->ContainsFpuRegister(fpu_reg)) { |
1508 __ vstrd(fpu_reg, Address(SP, offset)); | 1508 DRegister d1 = static_cast<DRegister>(fpu_reg * 2); |
1509 DRegister d2 = static_cast<DRegister>(fpu_reg * 2 + 1); | |
regis
2013/07/12 22:16:01
Use macros
zra
2013/07/12 23:22:18
Done.
| |
1510 __ vstrd(d1, Address(SP, offset)); | |
1511 __ vstrd(d2, Address(SP, offset + 2 * kWordSize)); | |
1509 offset += kFpuRegisterSize; | 1512 offset += kFpuRegisterSize; |
1510 } | 1513 } |
1511 } | 1514 } |
1512 ASSERT(offset == (fpu_regs_count * kFpuRegisterSize)); | 1515 ASSERT(offset == (fpu_regs_count * kFpuRegisterSize)); |
1513 } | 1516 } |
1514 | 1517 |
1515 // Store general purpose registers with the lowest register number at the | 1518 // Store general purpose registers with the lowest register number at the |
1516 // lowest address. | 1519 // lowest address. |
1517 const intptr_t cpu_registers = locs->live_registers()->cpu_registers(); | 1520 const intptr_t cpu_registers = locs->live_registers()->cpu_registers(); |
1518 ASSERT((cpu_registers & ~kAllCpuRegistersList) == 0); | 1521 ASSERT((cpu_registers & ~kAllCpuRegistersList) == 0); |
(...skipping 10 matching lines...) Expand all Loading... | |
1529 ASSERT((cpu_registers & ~kAllCpuRegistersList) == 0); | 1532 ASSERT((cpu_registers & ~kAllCpuRegistersList) == 0); |
1530 if (cpu_registers != 0) { | 1533 if (cpu_registers != 0) { |
1531 __ PopList(cpu_registers); | 1534 __ PopList(cpu_registers); |
1532 } | 1535 } |
1533 | 1536 |
1534 const intptr_t fpu_regs_count = locs->live_registers()->fpu_regs_count(); | 1537 const intptr_t fpu_regs_count = locs->live_registers()->fpu_regs_count(); |
1535 if (fpu_regs_count > 0) { | 1538 if (fpu_regs_count > 0) { |
1536 // Fpu registers have the lowest register number at the lowest address. | 1539 // Fpu registers have the lowest register number at the lowest address. |
1537 intptr_t offset = 0; | 1540 intptr_t offset = 0; |
1538 for (intptr_t reg_idx = 0; reg_idx < kNumberOfFpuRegisters; ++reg_idx) { | 1541 for (intptr_t reg_idx = 0; reg_idx < kNumberOfFpuRegisters; ++reg_idx) { |
1539 DRegister fpu_reg = static_cast<DRegister>(reg_idx); | 1542 QRegister fpu_reg = static_cast<QRegister>(reg_idx); |
1540 if (locs->live_registers()->ContainsFpuRegister(fpu_reg)) { | 1543 if (locs->live_registers()->ContainsFpuRegister(fpu_reg)) { |
1541 __ vldrd(fpu_reg, Address(SP, offset)); | 1544 DRegister d1 = static_cast<DRegister>(fpu_reg * 2); |
1545 DRegister d2 = static_cast<DRegister>(fpu_reg * 2 + 1); | |
1546 __ vldrd(d1, Address(SP, offset)); | |
1547 __ vldrd(d2, Address(SP, offset + 2 * kWordSize)); | |
1542 offset += kFpuRegisterSize; | 1548 offset += kFpuRegisterSize; |
1543 } | 1549 } |
1544 } | 1550 } |
1545 ASSERT(offset == (fpu_regs_count * kFpuRegisterSize)); | 1551 ASSERT(offset == (fpu_regs_count * kFpuRegisterSize)); |
1546 __ AddImmediate(SP, offset); | 1552 __ AddImmediate(SP, offset); |
1547 } | 1553 } |
1548 } | 1554 } |
1549 | 1555 |
1550 | 1556 |
1551 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data, | 1557 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data, |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1594 } | 1600 } |
1595 assembler()->Bind(&match_found); | 1601 assembler()->Bind(&match_found); |
1596 } | 1602 } |
1597 | 1603 |
1598 | 1604 |
1599 void FlowGraphCompiler::EmitDoubleCompareBranch(Condition true_condition, | 1605 void FlowGraphCompiler::EmitDoubleCompareBranch(Condition true_condition, |
1600 FpuRegister left, | 1606 FpuRegister left, |
1601 FpuRegister right, | 1607 FpuRegister right, |
1602 BranchInstr* branch) { | 1608 BranchInstr* branch) { |
1603 ASSERT(branch != NULL); | 1609 ASSERT(branch != NULL); |
1604 assembler()->vcmpd(left, right); | 1610 DRegister dleft = static_cast<DRegister>(left * 2); |
1611 DRegister dright = static_cast<DRegister>(right * 2); | |
1612 assembler()->vcmpd(dleft, dright); | |
1605 assembler()->vmstat(); | 1613 assembler()->vmstat(); |
1606 BlockEntryInstr* nan_result = (true_condition == NE) ? | 1614 BlockEntryInstr* nan_result = (true_condition == NE) ? |
1607 branch->true_successor() : branch->false_successor(); | 1615 branch->true_successor() : branch->false_successor(); |
1608 assembler()->b(GetJumpLabel(nan_result), VS); | 1616 assembler()->b(GetJumpLabel(nan_result), VS); |
1609 branch->EmitBranchOnCondition(this, true_condition); | 1617 branch->EmitBranchOnCondition(this, true_condition); |
1610 } | 1618 } |
1611 | 1619 |
1612 | 1620 |
1613 void FlowGraphCompiler::EmitDoubleCompareBool(Condition true_condition, | 1621 void FlowGraphCompiler::EmitDoubleCompareBool(Condition true_condition, |
1614 FpuRegister left, | 1622 FpuRegister left, |
1615 FpuRegister right, | 1623 FpuRegister right, |
1616 Register result) { | 1624 Register result) { |
1617 assembler()->vcmpd(left, right); | 1625 DRegister dleft = static_cast<DRegister>(left * 2); |
1626 DRegister dright = static_cast<DRegister>(right * 2); | |
1627 assembler()->vcmpd(dleft, dright); | |
1618 assembler()->vmstat(); | 1628 assembler()->vmstat(); |
1619 assembler()->LoadObject(result, Bool::False()); | 1629 assembler()->LoadObject(result, Bool::False()); |
1620 Label done; | 1630 Label done; |
1621 assembler()->b(&done, VS); // NaN -> false. | 1631 assembler()->b(&done, VS); // NaN -> false. |
1622 assembler()->LoadObject(result, Bool::True(), true_condition); | 1632 assembler()->LoadObject(result, Bool::True(), true_condition); |
1623 assembler()->Bind(&done); | 1633 assembler()->Bind(&done); |
1624 } | 1634 } |
1625 | 1635 |
1626 | 1636 |
1627 // Do not impelement or use this function. | 1637 // Do not impelement or use this function. |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1681 } else if (source.IsStackSlot()) { | 1691 } else if (source.IsStackSlot()) { |
1682 if (destination.IsRegister()) { | 1692 if (destination.IsRegister()) { |
1683 __ ldr(destination.reg(), source.ToStackSlotAddress()); | 1693 __ ldr(destination.reg(), source.ToStackSlotAddress()); |
1684 } else { | 1694 } else { |
1685 ASSERT(destination.IsStackSlot()); | 1695 ASSERT(destination.IsStackSlot()); |
1686 MoveMemoryToMemory(destination.ToStackSlotAddress(), | 1696 MoveMemoryToMemory(destination.ToStackSlotAddress(), |
1687 source.ToStackSlotAddress()); | 1697 source.ToStackSlotAddress()); |
1688 } | 1698 } |
1689 } else if (source.IsFpuRegister()) { | 1699 } else if (source.IsFpuRegister()) { |
1690 if (destination.IsFpuRegister()) { | 1700 if (destination.IsFpuRegister()) { |
1691 __ vmovd(destination.fpu_reg(), source.fpu_reg()); | 1701 DRegister dst = static_cast<DRegister>(destination.fpu_reg() * 2); |
1702 DRegister src = static_cast<DRegister>(source.fpu_reg() * 2); | |
1703 __ vmovd(dst, src); | |
1692 } else { | 1704 } else { |
1693 if (destination.IsDoubleStackSlot()) { | 1705 if (destination.IsDoubleStackSlot()) { |
1694 __ vstrd(source.fpu_reg(), destination.ToStackSlotAddress()); | 1706 DRegister src = static_cast<DRegister>(source.fpu_reg() * 2); |
1707 __ vstrd(src, destination.ToStackSlotAddress()); | |
1695 } else { | 1708 } else { |
1696 ASSERT(destination.IsQuadStackSlot()); | 1709 ASSERT(destination.IsQuadStackSlot()); |
1697 UNIMPLEMENTED(); | 1710 UNIMPLEMENTED(); |
1698 } | 1711 } |
1699 } | 1712 } |
1700 } else if (source.IsDoubleStackSlot()) { | 1713 } else if (source.IsDoubleStackSlot()) { |
1701 if (destination.IsFpuRegister()) { | 1714 if (destination.IsFpuRegister()) { |
1702 __ vldrd(destination.fpu_reg(), source.ToStackSlotAddress()); | 1715 DRegister dst = static_cast<DRegister>(destination.fpu_reg() * 2); |
1716 __ vldrd(dst, source.ToStackSlotAddress()); | |
1703 } else { | 1717 } else { |
1704 ASSERT(destination.IsDoubleStackSlot()); | 1718 ASSERT(destination.IsDoubleStackSlot()); |
1705 __ vldrd(DTMP, source.ToStackSlotAddress()); | 1719 __ vldrd(DTMP, source.ToStackSlotAddress()); |
1706 __ vstrd(DTMP, destination.ToStackSlotAddress()); | 1720 __ vstrd(DTMP, destination.ToStackSlotAddress()); |
1707 } | 1721 } |
1708 } else if (source.IsQuadStackSlot()) { | 1722 } else if (source.IsQuadStackSlot()) { |
1709 UNIMPLEMENTED(); | 1723 UNIMPLEMENTED(); |
1710 } else { | 1724 } else { |
1711 ASSERT(source.IsConstant()); | 1725 ASSERT(source.IsConstant()); |
1712 if (destination.IsRegister()) { | 1726 if (destination.IsRegister()) { |
(...skipping 20 matching lines...) Expand all Loading... | |
1733 __ mov(IP, ShifterOperand(source.reg())); | 1747 __ mov(IP, ShifterOperand(source.reg())); |
1734 __ mov(source.reg(), ShifterOperand(destination.reg())); | 1748 __ mov(source.reg(), ShifterOperand(destination.reg())); |
1735 __ mov(destination.reg(), ShifterOperand(IP)); | 1749 __ mov(destination.reg(), ShifterOperand(IP)); |
1736 } else if (source.IsRegister() && destination.IsStackSlot()) { | 1750 } else if (source.IsRegister() && destination.IsStackSlot()) { |
1737 Exchange(source.reg(), destination.ToStackSlotAddress()); | 1751 Exchange(source.reg(), destination.ToStackSlotAddress()); |
1738 } else if (source.IsStackSlot() && destination.IsRegister()) { | 1752 } else if (source.IsStackSlot() && destination.IsRegister()) { |
1739 Exchange(destination.reg(), source.ToStackSlotAddress()); | 1753 Exchange(destination.reg(), source.ToStackSlotAddress()); |
1740 } else if (source.IsStackSlot() && destination.IsStackSlot()) { | 1754 } else if (source.IsStackSlot() && destination.IsStackSlot()) { |
1741 Exchange(destination.ToStackSlotAddress(), source.ToStackSlotAddress()); | 1755 Exchange(destination.ToStackSlotAddress(), source.ToStackSlotAddress()); |
1742 } else if (source.IsFpuRegister() && destination.IsFpuRegister()) { | 1756 } else if (source.IsFpuRegister() && destination.IsFpuRegister()) { |
1743 __ vmovd(DTMP, source.fpu_reg()); | 1757 DRegister dst = static_cast<DRegister>(destination.fpu_reg() * 2); |
1744 __ vmovd(source.fpu_reg(), destination.fpu_reg()); | 1758 DRegister src = static_cast<DRegister>(source.fpu_reg() * 2); |
1745 __ vmovd(destination.fpu_reg(), DTMP); | 1759 __ vmovd(DTMP, src); |
1760 __ vmovd(src, dst); | |
1761 __ vmovd(dst, DTMP); | |
1746 } else if (source.IsFpuRegister() || destination.IsFpuRegister()) { | 1762 } else if (source.IsFpuRegister() || destination.IsFpuRegister()) { |
1747 ASSERT(destination.IsDoubleStackSlot() || | 1763 ASSERT(destination.IsDoubleStackSlot() || |
1748 destination.IsQuadStackSlot() || | 1764 destination.IsQuadStackSlot() || |
1749 source.IsDoubleStackSlot() || | 1765 source.IsDoubleStackSlot() || |
1750 source.IsQuadStackSlot()); | 1766 source.IsQuadStackSlot()); |
1751 bool double_width = destination.IsDoubleStackSlot() || | 1767 bool double_width = destination.IsDoubleStackSlot() || |
1752 source.IsDoubleStackSlot(); | 1768 source.IsDoubleStackSlot(); |
1753 DRegister reg = source.IsFpuRegister() ? source.fpu_reg() | 1769 QRegister qreg = source.IsFpuRegister() ? source.fpu_reg() |
1754 : destination.fpu_reg(); | 1770 : destination.fpu_reg(); |
1771 DRegister reg = static_cast<DRegister>(qreg * 2); | |
1755 const Address& slot_address = source.IsFpuRegister() | 1772 const Address& slot_address = source.IsFpuRegister() |
1756 ? destination.ToStackSlotAddress() | 1773 ? destination.ToStackSlotAddress() |
1757 : source.ToStackSlotAddress(); | 1774 : source.ToStackSlotAddress(); |
1758 | 1775 |
1759 if (double_width) { | 1776 if (double_width) { |
1760 __ vldrd(DTMP, slot_address); | 1777 __ vldrd(DTMP, slot_address); |
1761 __ vstrd(reg, slot_address); | 1778 __ vstrd(reg, slot_address); |
1762 __ vmovd(reg, DTMP); | 1779 __ vmovd(reg, DTMP); |
1763 } else { | 1780 } else { |
1764 UNIMPLEMENTED(); | 1781 UNIMPLEMENTED(); |
1765 } | 1782 } |
1766 } else if (source.IsDoubleStackSlot() && destination.IsDoubleStackSlot()) { | 1783 } else if (source.IsDoubleStackSlot() && destination.IsDoubleStackSlot()) { |
1767 const Address& source_slot_address = source.ToStackSlotAddress(); | 1784 const Address& source_slot_address = source.ToStackSlotAddress(); |
1768 const Address& destination_slot_address = destination.ToStackSlotAddress(); | 1785 const Address& destination_slot_address = destination.ToStackSlotAddress(); |
1769 | 1786 |
1770 ScratchFpuRegisterScope ensure_scratch(this, DTMP); | 1787 ScratchFpuRegisterScope ensure_scratch(this, QTMP); |
1788 DRegister scratch = static_cast<DRegister>(ensure_scratch.reg() * 2); | |
1771 __ vldrd(DTMP, source_slot_address); | 1789 __ vldrd(DTMP, source_slot_address); |
1772 __ vldrd(ensure_scratch.reg(), destination_slot_address); | 1790 __ vldrd(scratch, destination_slot_address); |
1773 __ vstrd(DTMP, destination_slot_address); | 1791 __ vstrd(DTMP, destination_slot_address); |
1774 __ vstrd(ensure_scratch.reg(), source_slot_address); | 1792 __ vstrd(scratch, source_slot_address); |
1775 } else if (source.IsQuadStackSlot() && destination.IsQuadStackSlot()) { | 1793 } else if (source.IsQuadStackSlot() && destination.IsQuadStackSlot()) { |
1776 UNIMPLEMENTED(); | 1794 UNIMPLEMENTED(); |
1777 } else { | 1795 } else { |
1778 UNREACHABLE(); | 1796 UNREACHABLE(); |
1779 } | 1797 } |
1780 | 1798 |
1781 // The swap of source and destination has executed a move from source to | 1799 // The swap of source and destination has executed a move from source to |
1782 // destination. | 1800 // destination. |
1783 move->Eliminate(); | 1801 move->Eliminate(); |
1784 | 1802 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1830 __ Push(reg); | 1848 __ Push(reg); |
1831 } | 1849 } |
1832 | 1850 |
1833 | 1851 |
1834 void ParallelMoveResolver::RestoreScratch(Register reg) { | 1852 void ParallelMoveResolver::RestoreScratch(Register reg) { |
1835 __ Pop(reg); | 1853 __ Pop(reg); |
1836 } | 1854 } |
1837 | 1855 |
1838 | 1856 |
1839 void ParallelMoveResolver::SpillFpuScratch(FpuRegister reg) { | 1857 void ParallelMoveResolver::SpillFpuScratch(FpuRegister reg) { |
1840 __ vstrd(reg, Address(SP, -kDoubleSize, Address::PreIndex)); | 1858 DRegister dreg = static_cast<DRegister>(reg * 2); |
1859 __ vstrd(dreg, Address(SP, -kDoubleSize, Address::PreIndex)); | |
1841 } | 1860 } |
1842 | 1861 |
1843 | 1862 |
1844 void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) { | 1863 void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) { |
1845 __ vldrd(reg, Address(SP, kDoubleSize, Address::PostIndex)); | 1864 DRegister dreg = static_cast<DRegister>(reg * 2); |
1865 __ vldrd(dreg, Address(SP, kDoubleSize, Address::PostIndex)); | |
1846 } | 1866 } |
1847 | 1867 |
1848 | 1868 |
1849 #undef __ | 1869 #undef __ |
1850 | 1870 |
1851 } // namespace dart | 1871 } // namespace dart |
1852 | 1872 |
1853 #endif // defined TARGET_ARCH_ARM | 1873 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |