Chromium Code Reviews| 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" | 5 #include "vm/globals.h" |
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 7 | 7 |
| 8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
| 9 #include "vm/heap.h" | 9 #include "vm/heap.h" |
| 10 #include "vm/memory_region.h" | 10 #include "vm/memory_region.h" |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 197 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 197 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 198 EmitUint8(0x68); | 198 EmitUint8(0x68); |
| 199 EmitImmediate(imm); | 199 EmitImmediate(imm); |
| 200 } else { | 200 } else { |
| 201 movq(TMP, imm); | 201 movq(TMP, imm); |
| 202 pushq(TMP); | 202 pushq(TMP); |
| 203 } | 203 } |
| 204 } | 204 } |
| 205 | 205 |
| 206 | 206 |
| 207 void Assembler::PushImmediate(const Immediate& imm, Register pp) { | |
| 208 if (imm.is_int32()) { | |
| 209 pushq(imm); | |
| 210 } else { | |
| 211 LoadImmediate(TMP, imm, pp); | |
| 212 pushq(TMP); | |
| 213 } | |
| 214 } | |
| 215 | |
| 216 | |
| 207 void Assembler::popq(Register reg) { | 217 void Assembler::popq(Register reg) { |
| 208 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 218 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 209 EmitRegisterREX(reg, REX_NONE); | 219 EmitRegisterREX(reg, REX_NONE); |
| 210 EmitUint8(0x58 | (reg & 7)); | 220 EmitUint8(0x58 | (reg & 7)); |
| 211 } | 221 } |
| 212 | 222 |
| 213 | 223 |
| 214 void Assembler::popq(const Address& address) { | 224 void Assembler::popq(const Address& address) { |
| 215 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 225 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 216 EmitOperandREX(0, address, REX_NONE); | 226 EmitOperandREX(0, address, REX_NONE); |
| (...skipping 589 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 806 } | 816 } |
| 807 | 817 |
| 808 void Assembler::notps(XmmRegister dst) { | 818 void Assembler::notps(XmmRegister dst) { |
| 809 static const struct ALIGN16 { | 819 static const struct ALIGN16 { |
| 810 uint32_t a; | 820 uint32_t a; |
| 811 uint32_t b; | 821 uint32_t b; |
| 812 uint32_t c; | 822 uint32_t c; |
| 813 uint32_t d; | 823 uint32_t d; |
| 814 } float_not_constant = | 824 } float_not_constant = |
| 815 { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; | 825 { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; |
| 816 movq(TMP, Immediate(reinterpret_cast<intptr_t>(&float_not_constant))); | 826 LoadImmediate( |
| 827 TMP, Immediate(reinterpret_cast<intptr_t>(&float_not_constant)), PP); | |
| 817 xorps(dst, Address(TMP, 0)); | 828 xorps(dst, Address(TMP, 0)); |
| 818 } | 829 } |
| 819 | 830 |
| 820 | 831 |
| 821 void Assembler::negateps(XmmRegister dst) { | 832 void Assembler::negateps(XmmRegister dst) { |
| 822 static const struct ALIGN16 { | 833 static const struct ALIGN16 { |
| 823 uint32_t a; | 834 uint32_t a; |
| 824 uint32_t b; | 835 uint32_t b; |
| 825 uint32_t c; | 836 uint32_t c; |
| 826 uint32_t d; | 837 uint32_t d; |
| 827 } float_negate_constant = | 838 } float_negate_constant = |
| 828 { 0x80000000, 0x80000000, 0x80000000, 0x80000000 }; | 839 { 0x80000000, 0x80000000, 0x80000000, 0x80000000 }; |
| 829 movq(TMP, Immediate(reinterpret_cast<intptr_t>(&float_negate_constant))); | 840 LoadImmediate( |
| 841 TMP, Immediate(reinterpret_cast<intptr_t>(&float_negate_constant)), PP); | |
| 830 xorps(dst, Address(TMP, 0)); | 842 xorps(dst, Address(TMP, 0)); |
| 831 } | 843 } |
| 832 | 844 |
| 833 | 845 |
| 834 void Assembler::absps(XmmRegister dst) { | 846 void Assembler::absps(XmmRegister dst) { |
| 835 static const struct ALIGN16 { | 847 static const struct ALIGN16 { |
| 836 uint32_t a; | 848 uint32_t a; |
| 837 uint32_t b; | 849 uint32_t b; |
| 838 uint32_t c; | 850 uint32_t c; |
| 839 uint32_t d; | 851 uint32_t d; |
| 840 } float_absolute_constant = | 852 } float_absolute_constant = |
| 841 { 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF }; | 853 { 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF }; |
| 842 movq(TMP, Immediate(reinterpret_cast<intptr_t>(&float_absolute_constant))); | 854 LoadImmediate( |
| 855 TMP, Immediate(reinterpret_cast<intptr_t>(&float_absolute_constant)), PP); | |
| 843 andps(dst, Address(TMP, 0)); | 856 andps(dst, Address(TMP, 0)); |
| 844 } | 857 } |
| 845 | 858 |
| 846 | 859 |
| 847 void Assembler::zerowps(XmmRegister dst) { | 860 void Assembler::zerowps(XmmRegister dst) { |
| 848 static const struct ALIGN16 { | 861 static const struct ALIGN16 { |
| 849 uint32_t a; | 862 uint32_t a; |
| 850 uint32_t b; | 863 uint32_t b; |
| 851 uint32_t c; | 864 uint32_t c; |
| 852 uint32_t d; | 865 uint32_t d; |
| 853 } float_zerow_constant = | 866 } float_zerow_constant = |
| 854 { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000 }; | 867 { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000 }; |
| 855 movq(TMP, Immediate(reinterpret_cast<intptr_t>(&float_zerow_constant))); | 868 LoadImmediate( |
| 869 TMP, Immediate(reinterpret_cast<intptr_t>(&float_zerow_constant)), PP); | |
| 856 andps(dst, Address(TMP, 0)); | 870 andps(dst, Address(TMP, 0)); |
| 857 } | 871 } |
| 858 | 872 |
| 859 | 873 |
| 860 void Assembler::cmppseq(XmmRegister dst, XmmRegister src) { | 874 void Assembler::cmppseq(XmmRegister dst, XmmRegister src) { |
| 861 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 875 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 862 EmitREX_RB(dst, src); | 876 EmitREX_RB(dst, src); |
| 863 EmitUint8(0x0F); | 877 EmitUint8(0x0F); |
| 864 EmitUint8(0xC2); | 878 EmitUint8(0xC2); |
| 865 EmitXmmRegisterOperand(dst & 7, src); | 879 EmitXmmRegisterOperand(dst & 7, src); |
| (...skipping 469 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1335 | 1349 |
| 1336 | 1350 |
| 1337 void Assembler::cmpq(Register reg, const Address& address) { | 1351 void Assembler::cmpq(Register reg, const Address& address) { |
| 1338 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 1352 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1339 EmitOperandREX(reg, address, REX_W); | 1353 EmitOperandREX(reg, address, REX_W); |
| 1340 EmitUint8(0x3B); | 1354 EmitUint8(0x3B); |
| 1341 EmitOperand(reg & 7, address); | 1355 EmitOperand(reg & 7, address); |
| 1342 } | 1356 } |
| 1343 | 1357 |
| 1344 | 1358 |
| 1359 void Assembler::CompareImmediate(Register reg, const Immediate& imm, | |
| 1360 Register pp) { | |
| 1361 if (imm.is_int32()) { | |
| 1362 cmpq(reg, imm); | |
| 1363 } else { | |
| 1364 LoadImmediate(TMP, imm, pp); | |
| 1365 cmpq(reg, TMP); | |
| 1366 } | |
| 1367 } | |
| 1368 | |
| 1369 | |
| 1370 void Assembler::CompareImmediate(const Address& address, const Immediate& imm, | |
| 1371 Register pp) { | |
| 1372 if (imm.is_int32()) { | |
| 1373 cmpq(address, imm); | |
| 1374 } else { | |
| 1375 LoadImmediate(TMP, imm, pp); | |
| 1376 cmpq(address, TMP); | |
| 1377 } | |
| 1378 } | |
| 1379 | |
| 1380 | |
| 1345 void Assembler::testl(Register reg1, Register reg2) { | 1381 void Assembler::testl(Register reg1, Register reg2) { |
| 1346 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 1382 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1347 Operand operand(reg2); | 1383 Operand operand(reg2); |
| 1348 EmitOperandREX(reg1, operand, REX_NONE); | 1384 EmitOperandREX(reg1, operand, REX_NONE); |
| 1349 EmitUint8(0x85); | 1385 EmitUint8(0x85); |
| 1350 EmitOperand(reg1 & 7, operand); | 1386 EmitOperand(reg1 & 7, operand); |
| 1351 } | 1387 } |
| 1352 | 1388 |
| 1353 | 1389 |
| 1354 void Assembler::testl(Register reg, const Immediate& imm) { | 1390 void Assembler::testl(Register reg, const Immediate& imm) { |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1485 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 1521 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1486 EmitRegisterREX(dst, REX_W); | 1522 EmitRegisterREX(dst, REX_W); |
| 1487 EmitComplex(4, Operand(dst), imm); | 1523 EmitComplex(4, Operand(dst), imm); |
| 1488 } else { | 1524 } else { |
| 1489 movq(TMP, imm); | 1525 movq(TMP, imm); |
| 1490 andq(dst, TMP); | 1526 andq(dst, TMP); |
| 1491 } | 1527 } |
| 1492 } | 1528 } |
| 1493 | 1529 |
| 1494 | 1530 |
| 1531 void Assembler::AndImmediate(Register dst, const Immediate& imm, Register pp) { | |
| 1532 if (imm.is_int32()) { | |
| 1533 andq(dst, imm); | |
| 1534 } else { | |
| 1535 ASSERT(dst != TMP); | |
| 1536 LoadImmediate(TMP, imm, pp); | |
| 1537 andq(dst, TMP); | |
| 1538 } | |
| 1539 } | |
| 1540 | |
| 1541 | |
| 1495 void Assembler::orq(Register dst, Register src) { | 1542 void Assembler::orq(Register dst, Register src) { |
| 1496 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 1543 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1497 Operand operand(src); | 1544 Operand operand(src); |
| 1498 EmitOperandREX(dst, operand, REX_W); | 1545 EmitOperandREX(dst, operand, REX_W); |
| 1499 EmitUint8(0x0B); | 1546 EmitUint8(0x0B); |
| 1500 EmitOperand(dst & 7, operand); | 1547 EmitOperand(dst & 7, operand); |
| 1501 } | 1548 } |
| 1502 | 1549 |
| 1503 | 1550 |
| 1504 void Assembler::orq(Register dst, const Address& address) { | 1551 void Assembler::orq(Register dst, const Address& address) { |
| 1505 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 1552 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1506 EmitOperandREX(dst, address, REX_W); | 1553 EmitOperandREX(dst, address, REX_W); |
| 1507 EmitUint8(0x0B); | 1554 EmitUint8(0x0B); |
| 1508 EmitOperand(dst & 7, address); | 1555 EmitOperand(dst & 7, address); |
| 1509 } | 1556 } |
| 1510 | 1557 |
| 1511 | 1558 |
| 1512 void Assembler::orq(Register dst, const Immediate& imm) { | 1559 void Assembler::orq(Register dst, const Immediate& imm) { |
| 1513 if (imm.is_int32()) { | 1560 if (imm.is_int32()) { |
| 1514 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 1561 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1515 EmitRegisterREX(dst, REX_W); | 1562 EmitRegisterREX(dst, REX_W); |
| 1516 EmitComplex(1, Operand(dst), imm); | 1563 EmitComplex(1, Operand(dst), imm); |
| 1517 } else { | 1564 } else { |
| 1518 movq(TMP, imm); | 1565 movq(TMP, imm); |
| 1519 orq(dst, TMP); | 1566 orq(dst, TMP); |
| 1520 } | 1567 } |
| 1521 } | 1568 } |
| 1522 | 1569 |
| 1523 | 1570 |
| 1571 void Assembler::OrImmediate(Register dst, const Immediate& imm, Register pp) { | |
| 1572 if (imm.is_int32()) { | |
| 1573 orq(dst, imm); | |
| 1574 } else { | |
| 1575 ASSERT(dst != TMP); | |
| 1576 LoadImmediate(TMP, imm, pp); | |
| 1577 orq(dst, TMP); | |
| 1578 } | |
| 1579 } | |
| 1580 | |
| 1581 | |
| 1524 void Assembler::xorq(Register dst, Register src) { | 1582 void Assembler::xorq(Register dst, Register src) { |
| 1525 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 1583 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1526 Operand operand(src); | 1584 Operand operand(src); |
| 1527 EmitOperandREX(dst, operand, REX_W); | 1585 EmitOperandREX(dst, operand, REX_W); |
| 1528 EmitUint8(0x33); | 1586 EmitUint8(0x33); |
| 1529 EmitOperand(dst & 7, operand); | 1587 EmitOperand(dst & 7, operand); |
| 1530 } | 1588 } |
| 1531 | 1589 |
| 1532 | 1590 |
| 1533 void Assembler::xorq(Register dst, const Address& address) { | 1591 void Assembler::xorq(Register dst, const Address& address) { |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 1551 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 1609 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1552 EmitRegisterREX(dst, REX_W); | 1610 EmitRegisterREX(dst, REX_W); |
| 1553 EmitComplex(6, Operand(dst), imm); | 1611 EmitComplex(6, Operand(dst), imm); |
| 1554 } else { | 1612 } else { |
| 1555 movq(TMP, imm); | 1613 movq(TMP, imm); |
| 1556 xorq(dst, TMP); | 1614 xorq(dst, TMP); |
| 1557 } | 1615 } |
| 1558 } | 1616 } |
| 1559 | 1617 |
| 1560 | 1618 |
| 1619 void Assembler::XorImmediate(Register dst, const Immediate& imm, Register pp) { | |
| 1620 if (imm.is_int32()) { | |
| 1621 xorq(dst, imm); | |
| 1622 } else { | |
| 1623 ASSERT(dst != TMP); | |
| 1624 LoadImmediate(TMP, imm, pp); | |
| 1625 xorq(dst, TMP); | |
| 1626 } | |
| 1627 } | |
| 1628 | |
| 1629 | |
| 1561 void Assembler::addl(Register dst, Register src) { | 1630 void Assembler::addl(Register dst, Register src) { |
| 1562 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 1631 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1563 Operand operand(src); | 1632 Operand operand(src); |
| 1564 EmitOperandREX(dst, operand, REX_NONE); | 1633 EmitOperandREX(dst, operand, REX_NONE); |
| 1565 EmitUint8(0x03); | 1634 EmitUint8(0x03); |
| 1566 EmitOperand(dst & 7, operand); | 1635 EmitOperand(dst & 7, operand); |
| 1567 } | 1636 } |
| 1568 | 1637 |
| 1569 | 1638 |
| 1570 void Assembler::addq(Register dst, Register src) { | 1639 void Assembler::addq(Register dst, Register src) { |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1701 EmitUint8(0x69); | 1770 EmitUint8(0x69); |
| 1702 EmitOperand(reg & 7, Operand(reg)); | 1771 EmitOperand(reg & 7, Operand(reg)); |
| 1703 EmitImmediate(imm); | 1772 EmitImmediate(imm); |
| 1704 } else { | 1773 } else { |
| 1705 movq(TMP, imm); | 1774 movq(TMP, imm); |
| 1706 imulq(reg, TMP); | 1775 imulq(reg, TMP); |
| 1707 } | 1776 } |
| 1708 } | 1777 } |
| 1709 | 1778 |
| 1710 | 1779 |
| 1780 void Assembler::MulImmediate(Register reg, const Immediate& imm, Register pp) { | |
| 1781 if (imm.is_int32()) { | |
| 1782 imulq(reg, imm); | |
| 1783 } else { | |
| 1784 ASSERT(reg != TMP); | |
| 1785 LoadImmediate(TMP, imm, pp); | |
| 1786 imulq(reg, TMP); | |
| 1787 } | |
| 1788 } | |
| 1789 | |
| 1790 | |
| 1711 void Assembler::imulq(Register dst, const Address& address) { | 1791 void Assembler::imulq(Register dst, const Address& address) { |
| 1712 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 1792 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1713 EmitOperandREX(dst, address, REX_W); | 1793 EmitOperandREX(dst, address, REX_W); |
| 1714 EmitUint8(0x0F); | 1794 EmitUint8(0x0F); |
| 1715 EmitUint8(0xAF); | 1795 EmitUint8(0xAF); |
| 1716 EmitOperand(dst & 7, address); | 1796 EmitOperand(dst & 7, address); |
| 1717 } | 1797 } |
| 1718 | 1798 |
| 1719 | 1799 |
| 1720 void Assembler::subq(Register dst, Register src) { | 1800 void Assembler::subq(Register dst, Register src) { |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 1739 | 1819 |
| 1740 | 1820 |
| 1741 void Assembler::subq(Register reg, const Address& address) { | 1821 void Assembler::subq(Register reg, const Address& address) { |
| 1742 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 1822 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1743 EmitOperandREX(reg, address, REX_W); | 1823 EmitOperandREX(reg, address, REX_W); |
| 1744 EmitUint8(0x2B); | 1824 EmitUint8(0x2B); |
| 1745 EmitOperand(reg & 7, address); | 1825 EmitOperand(reg & 7, address); |
| 1746 } | 1826 } |
| 1747 | 1827 |
| 1748 | 1828 |
| 1829 void Assembler::subq(const Address& address, Register reg) { | |
| 1830 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
| 1831 EmitOperandREX(reg, address, REX_W); | |
| 1832 EmitUint8(0x29); | |
| 1833 EmitOperand(reg & 7, address); | |
| 1834 } | |
| 1835 | |
| 1836 | |
| 1837 void Assembler::subq(const Address& address, const Immediate& imm) { | |
| 1838 // TODO(srdjan): Implement shorter version for imm32. | |
| 1839 movq(TMP, imm); | |
| 1840 subq(address, TMP); | |
| 1841 } | |
| 1842 | |
| 1843 | |
| 1749 void Assembler::shll(Register reg, const Immediate& imm) { | 1844 void Assembler::shll(Register reg, const Immediate& imm) { |
| 1750 EmitGenericShift(false, 4, reg, imm); | 1845 EmitGenericShift(false, 4, reg, imm); |
| 1751 } | 1846 } |
| 1752 | 1847 |
| 1753 | 1848 |
| 1754 void Assembler::shll(Register operand, Register shifter) { | 1849 void Assembler::shll(Register operand, Register shifter) { |
| 1755 EmitGenericShift(false, 4, operand, shifter); | 1850 EmitGenericShift(false, 4, operand, shifter); |
| 1756 } | 1851 } |
| 1757 | 1852 |
| 1758 | 1853 |
| (...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2131 movq(to, from); | 2226 movq(to, from); |
| 2132 } | 2227 } |
| 2133 } | 2228 } |
| 2134 | 2229 |
| 2135 | 2230 |
| 2136 void Assembler::PopRegister(Register r) { | 2231 void Assembler::PopRegister(Register r) { |
| 2137 popq(r); | 2232 popq(r); |
| 2138 } | 2233 } |
| 2139 | 2234 |
| 2140 | 2235 |
| 2141 void Assembler::AddImmediate(Register reg, const Immediate& imm) { | 2236 void Assembler::AddImmediate(Register reg, const Immediate& imm, Register pp) { |
| 2142 int64_t value = imm.value(); | 2237 int64_t value = imm.value(); |
| 2143 if (value > 0) { | 2238 if (value > 0) { |
| 2144 if (value == 1) { | 2239 if (value == 1) { |
| 2145 incq(reg); | 2240 incq(reg); |
| 2146 } else if (value != 0) { | 2241 } else if (value != 0) { |
| 2147 addq(reg, imm); | 2242 if (imm.is_int32()) { |
| 2243 addq(reg, imm); | |
| 2244 } else { | |
| 2245 ASSERT(reg != TMP); | |
| 2246 LoadImmediate(TMP, imm, pp); | |
| 2247 addq(reg, TMP); | |
| 2248 } | |
| 2148 } | 2249 } |
| 2149 } else if (value < 0) { | 2250 } else if (value < 0) { |
| 2150 value = -value; | 2251 value = -value; |
| 2151 if (value == 1) { | 2252 if (value == 1) { |
| 2152 decq(reg); | 2253 decq(reg); |
| 2153 } else if (value != 0) { | 2254 } else if (value != 0) { |
| 2154 subq(reg, Immediate(value)); | 2255 const Immediate& s = Immediate(value); |
| 2256 if (s.is_int32()) { | |
| 2257 subq(reg, Immediate(value)); | |
| 2258 } else { | |
| 2259 ASSERT(reg != TMP); | |
| 2260 LoadImmediate(TMP, s, pp); | |
| 2261 subq(reg, TMP); | |
| 2262 } | |
| 2263 } | |
| 2264 } | |
| 2265 } | |
| 2266 | |
| 2267 | |
| 2268 void Assembler::AddImmediate(const Address& address, const Immediate& imm, | |
| 2269 Register pp) { | |
| 2270 int64_t value = imm.value(); | |
| 2271 if (value > 0) { | |
| 2272 if (value == 1) { | |
| 2273 incq(address); | |
| 2274 } else if (value != 0) { | |
| 2275 if (imm.is_int32()) { | |
| 2276 addq(address, imm); | |
| 2277 } else { | |
| 2278 LoadImmediate(TMP, imm, pp); | |
| 2279 addq(address, TMP); | |
| 2280 } | |
| 2281 } | |
| 2282 } else if (value < 0) { | |
| 2283 value = -value; | |
| 2284 if (value == 1) { | |
| 2285 decq(address); | |
| 2286 } else if (value != 0) { | |
| 2287 const Immediate& s = Immediate(value); | |
| 2288 if (s.is_int32()) { | |
| 2289 subq(address, s); | |
| 2290 } else { | |
| 2291 LoadImmediate(TMP, s, pp); | |
| 2292 subq(address, TMP); | |
| 2293 } | |
| 2155 } | 2294 } |
| 2156 } | 2295 } |
| 2157 } | 2296 } |
| 2158 | 2297 |
| 2159 | 2298 |
| 2160 void Assembler::Drop(intptr_t stack_elements) { | 2299 void Assembler::Drop(intptr_t stack_elements) { |
| 2161 ASSERT(stack_elements >= 0); | 2300 ASSERT(stack_elements >= 0); |
| 2162 if (stack_elements <= 4) { | 2301 if (stack_elements <= 4) { |
| 2163 for (intptr_t i = 0; i < stack_elements; i++) { | 2302 for (intptr_t i = 0; i < stack_elements; i++) { |
| 2164 popq(TMP); | 2303 popq(TMP); |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2254 | 2393 |
| 2255 void Assembler::LoadObject(Register dst, const Object& object, Register pp) { | 2394 void Assembler::LoadObject(Register dst, const Object& object, Register pp) { |
| 2256 if (CanLoadFromObjectPool(object)) { | 2395 if (CanLoadFromObjectPool(object)) { |
| 2257 const int32_t offset = | 2396 const int32_t offset = |
| 2258 Array::element_offset(FindObject(object, kNotPatchable)); | 2397 Array::element_offset(FindObject(object, kNotPatchable)); |
| 2259 LoadWordFromPoolOffset(dst, pp, offset - kHeapObjectTag); | 2398 LoadWordFromPoolOffset(dst, pp, offset - kHeapObjectTag); |
| 2260 } else { | 2399 } else { |
| 2261 ASSERT((Isolate::Current() == Dart::vm_isolate()) || | 2400 ASSERT((Isolate::Current() == Dart::vm_isolate()) || |
| 2262 object.IsSmi() || | 2401 object.IsSmi() || |
| 2263 object.InVMHeap()); | 2402 object.InVMHeap()); |
| 2264 movq(dst, Immediate(reinterpret_cast<int64_t>(object.raw()))); | 2403 LoadImmediate(dst, Immediate(reinterpret_cast<int64_t>(object.raw())), pp); |
| 2265 } | 2404 } |
| 2266 } | 2405 } |
| 2267 | 2406 |
| 2268 | 2407 |
| 2269 void Assembler::StoreObject(const Address& dst, const Object& object) { | 2408 void Assembler::StoreObject(const Address& dst, const Object& object, |
| 2409 Register pp) { | |
| 2270 if (CanLoadFromObjectPool(object)) { | 2410 if (CanLoadFromObjectPool(object)) { |
| 2271 LoadObject(TMP, object, PP); | 2411 LoadObject(TMP, object, pp); |
| 2272 movq(dst, TMP); | 2412 movq(dst, TMP); |
| 2273 } else { | 2413 } else { |
| 2274 movq(dst, Immediate(reinterpret_cast<int64_t>(object.raw()))); | 2414 LoadImmediate(dst, Immediate(reinterpret_cast<int64_t>(object.raw())), pp); |
| 2275 } | 2415 } |
| 2276 } | 2416 } |
| 2277 | 2417 |
| 2278 | 2418 |
| 2279 void Assembler::PushObject(const Object& object) { | 2419 void Assembler::PushObject(const Object& object, Register pp) { |
| 2280 if (CanLoadFromObjectPool(object)) { | 2420 if (CanLoadFromObjectPool(object)) { |
| 2281 LoadObject(TMP, object, PP); | 2421 LoadObject(TMP, object, pp); |
| 2282 pushq(TMP); | 2422 pushq(TMP); |
| 2283 } else { | 2423 } else { |
| 2284 pushq(Immediate(reinterpret_cast<int64_t>(object.raw()))); | 2424 PushImmediate(Immediate(reinterpret_cast<int64_t>(object.raw())), pp); |
| 2285 } | 2425 } |
| 2286 } | 2426 } |
| 2287 | 2427 |
| 2288 | 2428 |
| 2289 void Assembler::CompareObject(Register reg, const Object& object) { | 2429 void Assembler::CompareObject(Register reg, const Object& object, Register pp) { |
| 2290 if (CanLoadFromObjectPool(object)) { | 2430 if (CanLoadFromObjectPool(object)) { |
| 2291 ASSERT(reg != TMP); | 2431 ASSERT(reg != TMP); |
| 2292 LoadObject(TMP, object, PP); | 2432 LoadObject(TMP, object, pp); |
| 2293 cmpq(reg, TMP); | 2433 cmpq(reg, TMP); |
| 2294 } else { | 2434 } else { |
| 2295 cmpq(reg, Immediate(reinterpret_cast<int64_t>(object.raw()))); | 2435 CompareImmediate( |
| 2436 reg, Immediate(reinterpret_cast<int64_t>(object.raw())), pp); | |
| 2437 } | |
| 2438 } | |
| 2439 | |
| 2440 | |
| 2441 intptr_t Assembler::FindImmediate(int64_t imm) { | |
| 2442 ASSERT(Isolate::Current() != Dart::vm_isolate()); | |
| 2443 ASSERT(!object_pool_.IsNull()); | |
| 2444 const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(imm)); | |
| 2445 return FindObject(smi, kNotPatchable); | |
| 2446 } | |
| 2447 | |
| 2448 | |
| 2449 void Assembler::LoadImmediate(Register reg, const Immediate& imm, Register pp) { | |
| 2450 if (imm.is_int32() || | |
| 2451 (pp == kNoRegister) || | |
| 2452 (Isolate::Current() == Dart::vm_isolate())) { | |
| 2453 movq(reg, imm); | |
| 2454 } else { | |
| 2455 // It's a 64-bit constant and we're not in the VM isolate, so load form | |
|
Florian Schneider
2013/09/30 11:48:35
/s/form/from/
zra
2013/09/30 18:01:08
Done.
| |
| 2456 // object pool. | |
| 2457 int64_t val = imm.value(); | |
| 2458 // Save the bits that must be masked-off for the SmiTag | |
| 2459 int64_t val_smi_tag = val & kSmiTagMask; | |
| 2460 val &= ~kSmiTagMask; // Mask off the tag bits. | |
| 2461 const int32_t offset = Array::element_offset(FindImmediate(val)); | |
| 2462 LoadWordFromPoolOffset(reg, pp, offset - kHeapObjectTag); | |
| 2463 if (val_smi_tag != 0) { | |
| 2464 // Add back the tag bits. | |
| 2465 orq(reg, Immediate(val_smi_tag)); | |
| 2466 } | |
| 2467 } | |
| 2468 } | |
| 2469 | |
| 2470 | |
| 2471 void Assembler::LoadImmediate(const Address& dst, const Immediate& imm, | |
| 2472 Register pp) { | |
| 2473 if (imm.is_int32()) { | |
| 2474 movq(dst, imm); | |
| 2475 } else { | |
| 2476 LoadImmediate(TMP, imm, pp); | |
|
Florian Schneider
2013/09/30 11:48:35
This does not emit the most compact code in the ca
zra
2013/09/30 18:01:08
Done.
| |
| 2477 movq(dst, TMP); | |
| 2296 } | 2478 } |
| 2297 } | 2479 } |
| 2298 | 2480 |
| 2299 | 2481 |
| 2300 // Destroys the value register. | 2482 // Destroys the value register. |
| 2301 void Assembler::StoreIntoObjectFilterNoSmi(Register object, | 2483 void Assembler::StoreIntoObjectFilterNoSmi(Register object, |
| 2302 Register value, | 2484 Register value, |
| 2303 Label* no_update) { | 2485 Label* no_update) { |
| 2304 COMPILE_ASSERT((kNewObjectAlignmentOffset == kWordSize) && | 2486 COMPILE_ASSERT((kNewObjectAlignmentOffset == kWordSize) && |
| 2305 (kOldObjectAlignmentOffset == 0), young_alignment); | 2487 (kOldObjectAlignmentOffset == 0), young_alignment); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2376 // No store buffer update. | 2558 // No store buffer update. |
| 2377 } | 2559 } |
| 2378 | 2560 |
| 2379 | 2561 |
| 2380 void Assembler::DoubleNegate(XmmRegister d) { | 2562 void Assembler::DoubleNegate(XmmRegister d) { |
| 2381 static const struct ALIGN16 { | 2563 static const struct ALIGN16 { |
| 2382 uint64_t a; | 2564 uint64_t a; |
| 2383 uint64_t b; | 2565 uint64_t b; |
| 2384 } double_negate_constant = | 2566 } double_negate_constant = |
| 2385 {0x8000000000000000LL, 0x8000000000000000LL}; | 2567 {0x8000000000000000LL, 0x8000000000000000LL}; |
| 2386 movq(TMP, Immediate(reinterpret_cast<intptr_t>(&double_negate_constant))); | 2568 LoadImmediate( |
| 2569 TMP, Immediate(reinterpret_cast<intptr_t>(&double_negate_constant)), PP); | |
| 2387 xorpd(d, Address(TMP, 0)); | 2570 xorpd(d, Address(TMP, 0)); |
| 2388 } | 2571 } |
| 2389 | 2572 |
| 2390 | 2573 |
| 2391 void Assembler::DoubleAbs(XmmRegister reg) { | 2574 void Assembler::DoubleAbs(XmmRegister reg) { |
| 2392 static const struct ALIGN16 { | 2575 static const struct ALIGN16 { |
| 2393 uint64_t a; | 2576 uint64_t a; |
| 2394 uint64_t b; | 2577 uint64_t b; |
| 2395 } double_abs_constant = | 2578 } double_abs_constant = |
| 2396 {0x7FFFFFFFFFFFFFFFLL, 0x7FFFFFFFFFFFFFFFLL}; | 2579 {0x7FFFFFFFFFFFFFFFLL, 0x7FFFFFFFFFFFFFFFLL}; |
| 2397 movq(TMP, Immediate(reinterpret_cast<intptr_t>(&double_abs_constant))); | 2580 LoadImmediate(TMP, |
| 2581 Immediate(reinterpret_cast<intptr_t>(&double_abs_constant)), PP); | |
| 2398 andpd(reg, Address(TMP, 0)); | 2582 andpd(reg, Address(TMP, 0)); |
| 2399 } | 2583 } |
| 2400 | 2584 |
| 2401 | 2585 |
| 2402 void Assembler::Stop(const char* message) { | 2586 void Assembler::Stop(const char* message) { |
| 2403 int64_t message_address = reinterpret_cast<int64_t>(message); | 2587 int64_t message_address = reinterpret_cast<int64_t>(message); |
| 2404 if (FLAG_print_stop_message) { | 2588 if (FLAG_print_stop_message) { |
| 2405 pushq(TMP); // Preserve TMP register. | 2589 pushq(TMP); // Preserve TMP register. |
| 2406 pushq(RDI); // Preserve RDI register. | 2590 pushq(RDI); // Preserve RDI register. |
| 2407 movq(RDI, Immediate(message_address)); | 2591 LoadImmediate(RDI, Immediate(message_address), PP); |
| 2408 call(&StubCode::PrintStopMessageLabel()); | 2592 call(&StubCode::PrintStopMessageLabel()); |
| 2409 popq(RDI); // Restore RDI register. | 2593 popq(RDI); // Restore RDI register. |
| 2410 popq(TMP); // Restore TMP register. | 2594 popq(TMP); // Restore TMP register. |
| 2411 } else { | 2595 } else { |
| 2412 // Emit the lower half and the higher half of the message address as | 2596 // Emit the lower half and the higher half of the message address as |
| 2413 // immediate operands in the test rax instructions. | 2597 // immediate operands in the test rax instructions. |
| 2414 testl(RAX, Immediate(Utils::Low32Bits(message_address))); | 2598 testl(RAX, Immediate(Utils::Low32Bits(message_address))); |
| 2415 testl(RAX, Immediate(Utils::High32Bits(message_address))); | 2599 testl(RAX, Immediate(Utils::High32Bits(message_address))); |
| 2416 } | 2600 } |
| 2417 // Emit the int3 instruction. | 2601 // Emit the int3 instruction. |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2470 LeaveFrameWithPP(); | 2654 LeaveFrameWithPP(); |
| 2471 ret(); | 2655 ret(); |
| 2472 nop(4); | 2656 nop(4); |
| 2473 ASSERT((buffer_.GetPosition() - start) == 13); | 2657 ASSERT((buffer_.GetPosition() - start) == 13); |
| 2474 } | 2658 } |
| 2475 | 2659 |
| 2476 | 2660 |
| 2477 void Assembler::ReserveAlignedFrameSpace(intptr_t frame_space) { | 2661 void Assembler::ReserveAlignedFrameSpace(intptr_t frame_space) { |
| 2478 // Reserve space for arguments and align frame before entering | 2662 // Reserve space for arguments and align frame before entering |
| 2479 // the C++ world. | 2663 // the C++ world. |
| 2480 AddImmediate(RSP, Immediate(-frame_space)); | 2664 if (frame_space != 0) { |
| 2665 subq(RSP, Immediate(frame_space)); | |
| 2666 } | |
| 2481 if (OS::ActivationFrameAlignment() > 1) { | 2667 if (OS::ActivationFrameAlignment() > 1) { |
| 2482 andq(RSP, Immediate(~(OS::ActivationFrameAlignment() - 1))); | 2668 andq(RSP, Immediate(~(OS::ActivationFrameAlignment() - 1))); |
| 2483 } | 2669 } |
| 2484 } | 2670 } |
| 2485 | 2671 |
| 2486 | 2672 |
| 2487 // TODO(srdjan): Add XMM registers once they are used by the compiler. | 2673 // TODO(srdjan): Add XMM registers once they are used by the compiler. |
| 2488 // Based on http://x86-64.org/documentation/abi.pdf Fig. 3.4 | 2674 // Based on http://x86-64.org/documentation/abi.pdf Fig. 3.4 |
| 2489 static const intptr_t kNumberOfVolatileCpuRegisters = 9; | 2675 static const intptr_t kNumberOfVolatileCpuRegisters = 9; |
| 2490 static const Register volatile_cpu_registers[kNumberOfVolatileCpuRegisters] = { | 2676 static const Register volatile_cpu_registers[kNumberOfVolatileCpuRegisters] = { |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2660 EnterFrame(0); | 2846 EnterFrame(0); |
| 2661 pushq(Immediate(0)); // Push 0 in the saved PC area for stub frames. | 2847 pushq(Immediate(0)); // Push 0 in the saved PC area for stub frames. |
| 2662 pushq(PP); // Save caller's pool pointer | 2848 pushq(PP); // Save caller's pool pointer |
| 2663 LoadPoolPointer(PP); | 2849 LoadPoolPointer(PP); |
| 2664 } | 2850 } |
| 2665 | 2851 |
| 2666 | 2852 |
| 2667 void Assembler::TryAllocate(const Class& cls, | 2853 void Assembler::TryAllocate(const Class& cls, |
| 2668 Label* failure, | 2854 Label* failure, |
| 2669 bool near_jump, | 2855 bool near_jump, |
| 2670 Register instance_reg) { | 2856 Register instance_reg, |
| 2857 Register pp) { | |
| 2671 ASSERT(failure != NULL); | 2858 ASSERT(failure != NULL); |
| 2672 if (FLAG_inline_alloc) { | 2859 if (FLAG_inline_alloc) { |
| 2673 Heap* heap = Isolate::Current()->heap(); | 2860 Heap* heap = Isolate::Current()->heap(); |
| 2674 const intptr_t instance_size = cls.instance_size(); | 2861 const intptr_t instance_size = cls.instance_size(); |
| 2675 movq(TMP, Immediate(heap->TopAddress())); | 2862 LoadImmediate(TMP, Immediate(heap->TopAddress()), pp); |
| 2676 movq(instance_reg, Address(TMP, 0)); | 2863 movq(instance_reg, Address(TMP, 0)); |
| 2677 addq(instance_reg, Immediate(instance_size)); | 2864 AddImmediate(instance_reg, Immediate(instance_size), pp); |
| 2678 // instance_reg: potential next object start. | 2865 // instance_reg: potential next object start. |
| 2679 movq(TMP, Immediate(heap->EndAddress())); | 2866 LoadImmediate(TMP, Immediate(heap->EndAddress()), pp); |
| 2680 cmpq(instance_reg, Address(TMP, 0)); | 2867 cmpq(instance_reg, Address(TMP, 0)); |
| 2681 j(ABOVE_EQUAL, failure, near_jump); | 2868 j(ABOVE_EQUAL, failure, near_jump); |
| 2682 // Successfully allocated the object, now update top to point to | 2869 // Successfully allocated the object, now update top to point to |
| 2683 // next object start and store the class in the class field of object. | 2870 // next object start and store the class in the class field of object. |
| 2684 movq(TMP, Immediate(heap->TopAddress())); | 2871 LoadImmediate(TMP, Immediate(heap->TopAddress()), pp); |
| 2685 movq(Address(TMP, 0), instance_reg); | 2872 movq(Address(TMP, 0), instance_reg); |
| 2686 ASSERT(instance_size >= kHeapObjectTag); | 2873 ASSERT(instance_size >= kHeapObjectTag); |
| 2687 subq(instance_reg, Immediate(instance_size - kHeapObjectTag)); | 2874 AddImmediate(instance_reg, Immediate(kHeapObjectTag - instance_size), pp); |
| 2688 uword tags = 0; | 2875 uword tags = 0; |
| 2689 tags = RawObject::SizeTag::update(instance_size, tags); | 2876 tags = RawObject::SizeTag::update(instance_size, tags); |
| 2690 ASSERT(cls.id() != kIllegalCid); | 2877 ASSERT(cls.id() != kIllegalCid); |
| 2691 tags = RawObject::ClassIdTag::update(cls.id(), tags); | 2878 tags = RawObject::ClassIdTag::update(cls.id(), tags); |
| 2692 movq(FieldAddress(instance_reg, Object::tags_offset()), Immediate(tags)); | 2879 LoadImmediate(FieldAddress(instance_reg, Object::tags_offset()), |
| 2880 Immediate(tags), pp); | |
| 2693 } else { | 2881 } else { |
| 2694 jmp(failure); | 2882 jmp(failure); |
| 2695 } | 2883 } |
| 2696 } | 2884 } |
| 2697 | 2885 |
| 2698 | 2886 |
| 2699 void Assembler::Align(int alignment, int offset) { | 2887 void Assembler::Align(int alignment, int offset) { |
| 2700 ASSERT(Utils::IsPowerOfTwo(alignment)); | 2888 ASSERT(Utils::IsPowerOfTwo(alignment)); |
| 2701 int pos = offset + buffer_.GetPosition(); | 2889 int pos = offset + buffer_.GetPosition(); |
| 2702 int mod = pos & (alignment - 1); | 2890 int mod = pos & (alignment - 1); |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2882 | 3070 |
| 2883 | 3071 |
| 2884 const char* Assembler::FpuRegisterName(FpuRegister reg) { | 3072 const char* Assembler::FpuRegisterName(FpuRegister reg) { |
| 2885 ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters)); | 3073 ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters)); |
| 2886 return xmm_reg_names[reg]; | 3074 return xmm_reg_names[reg]; |
| 2887 } | 3075 } |
| 2888 | 3076 |
| 2889 } // namespace dart | 3077 } // namespace dart |
| 2890 | 3078 |
| 2891 #endif // defined TARGET_ARCH_X64 | 3079 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |