OLD | NEW |
---|---|
1 // Copyright (c) 1994-2006 Sun Microsystems Inc. | 1 // Copyright (c) 1994-2006 Sun Microsystems Inc. |
2 // All Rights Reserved. | 2 // All Rights Reserved. |
3 // | 3 // |
4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
5 // modification, are permitted provided that the following conditions | 5 // modification, are permitted provided that the following conditions |
6 // are met: | 6 // are met: |
7 // | 7 // |
8 // - Redistributions of source code must retain the above copyright notice, | 8 // - Redistributions of source code must retain the above copyright notice, |
9 // this list of conditions and the following disclaimer. | 9 // this list of conditions and the following disclaimer. |
10 // | 10 // |
(...skipping 1662 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1673 } | 1673 } |
1674 | 1674 |
1675 | 1675 |
1676 // Support for VFP. | 1676 // Support for VFP. |
1677 | 1677 |
1678 void Assembler::vldr(const DwVfpRegister dst, | 1678 void Assembler::vldr(const DwVfpRegister dst, |
1679 const Register base, | 1679 const Register base, |
1680 int offset, | 1680 int offset, |
1681 const Condition cond) { | 1681 const Condition cond) { |
1682 // Ddst = MEM(Rbase + offset). | 1682 // Ddst = MEM(Rbase + offset). |
1683 // Instruction details available in ARM DDI 0406A, A8-628. | 1683 // Instruction details available in ARM DDI 0406C.b, A8-924. |
1684 // cond(31-28) | 1101(27-24)| U001(23-20) | Rbase(19-16) | | 1684 // cond(31-28) | 1101(27-24)| U(23) | D(22) | 01(21-20) | Rbase(19-16) | |
1685 // Vdst(15-12) | 1011(11-8) | offset | 1685 // Vd(15-12) | 1011(11-8) | offset |
1686 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 1686 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
1687 int u = 1; | 1687 int u = 1; |
1688 if (offset < 0) { | 1688 if (offset < 0) { |
1689 offset = -offset; | 1689 offset = -offset; |
1690 u = 0; | 1690 u = 0; |
1691 } | 1691 } |
1692 ASSERT(offset >= 0); | |
Rodolph Perfetta
2012/12/12 14:29:15
There is the same assert two lines below.
hans
2012/12/12 17:58:47
Removed.
| |
1693 int vd, d; | |
1694 dst.split_code(&vd, &d); | |
1692 | 1695 |
1693 ASSERT(offset >= 0); | 1696 ASSERT(offset >= 0); |
1694 if ((offset % 4) == 0 && (offset / 4) < 256) { | 1697 if ((offset % 4) == 0 && (offset / 4) < 256) { |
1695 emit(cond | u*B23 | 0xD1*B20 | base.code()*B16 | dst.code()*B12 | | 1698 emit(cond | 0xD*B24 | u*B23 | d*B22 | B20 | base.code()*B16 | vd*B12 | |
1696 0xB*B8 | ((offset / 4) & 255)); | 1699 0xB*B8 | ((offset / 4) & 255)); |
1697 } else { | 1700 } else { |
1698 // Larger offsets must be handled by computing the correct address | 1701 // Larger offsets must be handled by computing the correct address |
1699 // in the ip register. | 1702 // in the ip register. |
1700 ASSERT(!base.is(ip)); | 1703 ASSERT(!base.is(ip)); |
1701 if (u == 1) { | 1704 if (u == 1) { |
1702 add(ip, base, Operand(offset)); | 1705 add(ip, base, Operand(offset)); |
1703 } else { | 1706 } else { |
1704 sub(ip, base, Operand(offset)); | 1707 sub(ip, base, Operand(offset)); |
1705 } | 1708 } |
1706 emit(cond | 0xD1*B20 | ip.code()*B16 | dst.code()*B12 | 0xB*B8); | 1709 emit(cond | 0xD*B24 | d*B22 | B20 | ip.code()*B16 | vd*B12 | 0xB*B8); |
1707 } | 1710 } |
1708 } | 1711 } |
1709 | 1712 |
1710 | 1713 |
1711 void Assembler::vldr(const DwVfpRegister dst, | 1714 void Assembler::vldr(const DwVfpRegister dst, |
1712 const MemOperand& operand, | 1715 const MemOperand& operand, |
1713 const Condition cond) { | 1716 const Condition cond) { |
1714 ASSERT(!operand.rm().is_valid()); | 1717 ASSERT(!operand.rm().is_valid()); |
1715 ASSERT(operand.am_ == Offset); | 1718 ASSERT(operand.am_ == Offset); |
1716 vldr(dst, operand.rn(), operand.offset(), cond); | 1719 vldr(dst, operand.rn(), operand.offset(), cond); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1759 ASSERT(operand.am_ == Offset); | 1762 ASSERT(operand.am_ == Offset); |
1760 vldr(dst, operand.rn(), operand.offset(), cond); | 1763 vldr(dst, operand.rn(), operand.offset(), cond); |
1761 } | 1764 } |
1762 | 1765 |
1763 | 1766 |
1764 void Assembler::vstr(const DwVfpRegister src, | 1767 void Assembler::vstr(const DwVfpRegister src, |
1765 const Register base, | 1768 const Register base, |
1766 int offset, | 1769 int offset, |
1767 const Condition cond) { | 1770 const Condition cond) { |
1768 // MEM(Rbase + offset) = Dsrc. | 1771 // MEM(Rbase + offset) = Dsrc. |
1769 // Instruction details available in ARM DDI 0406A, A8-786. | 1772 // Instruction details available in ARM DDI 0406C.b, A8-1082. |
1770 // cond(31-28) | 1101(27-24)| U000(23-20) | | Rbase(19-16) | | 1773 // cond(31-28) | 1101(27-24)| U(23) | D(22) | 00(21-20) | Rbase(19-16) | |
1771 // Vsrc(15-12) | 1011(11-8) | (offset/4) | 1774 // Vd(15-12) | 1011(11-8) | (offset/4) |
1772 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 1775 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
1773 int u = 1; | 1776 int u = 1; |
1774 if (offset < 0) { | 1777 if (offset < 0) { |
1775 offset = -offset; | 1778 offset = -offset; |
1776 u = 0; | 1779 u = 0; |
1777 } | 1780 } |
1778 ASSERT(offset >= 0); | 1781 ASSERT(offset >= 0); |
1782 int vd, d; | |
1783 src.split_code(&vd, &d); | |
1784 | |
1779 if ((offset % 4) == 0 && (offset / 4) < 256) { | 1785 if ((offset % 4) == 0 && (offset / 4) < 256) { |
1780 emit(cond | u*B23 | 0xD0*B20 | base.code()*B16 | src.code()*B12 | | 1786 emit(cond | 0xD*B24 | u*B23 | d*B22 | base.code()*B16 | vd*B12 | 0xB*B8 | |
1781 0xB*B8 | ((offset / 4) & 255)); | 1787 ((offset / 4) & 255)); |
1782 } else { | 1788 } else { |
1783 // Larger offsets must be handled by computing the correct address | 1789 // Larger offsets must be handled by computing the correct address |
1784 // in the ip register. | 1790 // in the ip register. |
1785 ASSERT(!base.is(ip)); | 1791 ASSERT(!base.is(ip)); |
1786 if (u == 1) { | 1792 if (u == 1) { |
1787 add(ip, base, Operand(offset)); | 1793 add(ip, base, Operand(offset)); |
1788 } else { | 1794 } else { |
1789 sub(ip, base, Operand(offset)); | 1795 sub(ip, base, Operand(offset)); |
1790 } | 1796 } |
1791 emit(cond | 0xD0*B20 | ip.code()*B16 | src.code()*B12 | 0xB*B8); | 1797 emit(cond | 0xD*B24 | d*B22 | ip.code()*B16 | vd*B12 | 0xB*B8); |
1792 } | 1798 } |
1793 } | 1799 } |
1794 | 1800 |
1795 | 1801 |
1796 void Assembler::vstr(const DwVfpRegister src, | 1802 void Assembler::vstr(const DwVfpRegister src, |
1797 const MemOperand& operand, | 1803 const MemOperand& operand, |
1798 const Condition cond) { | 1804 const Condition cond) { |
1799 ASSERT(!operand.rm().is_valid()); | 1805 ASSERT(!operand.rm().is_valid()); |
1800 ASSERT(operand.am_ == Offset); | 1806 ASSERT(operand.am_ == Offset); |
1801 vstr(src, operand.rn(), operand.offset(), cond); | 1807 vstr(src, operand.rn(), operand.offset(), cond); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1843 ASSERT(operand.am_ == Offset); | 1849 ASSERT(operand.am_ == Offset); |
1844 vstr(src, operand.rn(), operand.offset(), cond); | 1850 vstr(src, operand.rn(), operand.offset(), cond); |
1845 } | 1851 } |
1846 | 1852 |
1847 | 1853 |
1848 void Assembler::vldm(BlockAddrMode am, | 1854 void Assembler::vldm(BlockAddrMode am, |
1849 Register base, | 1855 Register base, |
1850 DwVfpRegister first, | 1856 DwVfpRegister first, |
1851 DwVfpRegister last, | 1857 DwVfpRegister last, |
1852 Condition cond) { | 1858 Condition cond) { |
1853 // Instruction details available in ARM DDI 0406A, A8-626. | 1859 // Instruction details available in ARM DDI 0406C.b, A8-922. |
1854 // cond(31-28) | 110(27-25)| PUDW1(24-20) | Rbase(19-16) | | 1860 // cond(31-28) | 110(27-25)| PUDW1(24-20) | Rbase(19-16) | |
1855 // first(15-12) | 1010(11-8) | (count * 2) | 1861 // first(15-12) | 1011(11-8) | (count * 2) |
1856 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 1862 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
1857 ASSERT_LE(first.code(), last.code()); | 1863 ASSERT_LE(first.code(), last.code()); |
1858 ASSERT(am == ia || am == ia_w || am == db_w); | 1864 ASSERT(am == ia || am == ia_w || am == db_w); |
1859 ASSERT(!base.is(pc)); | 1865 ASSERT(!base.is(pc)); |
1860 | 1866 |
1861 int sd, d; | 1867 int sd, d; |
1862 first.split_code(&sd, &d); | 1868 first.split_code(&sd, &d); |
1863 int count = last.code() - first.code() + 1; | 1869 int count = last.code() - first.code() + 1; |
1864 ASSERT(count <= 16); | 1870 ASSERT(count <= 16); |
1865 emit(cond | B27 | B26 | am | d*B22 | B20 | base.code()*B16 | sd*B12 | | 1871 emit(cond | B27 | B26 | am | d*B22 | B20 | base.code()*B16 | sd*B12 | |
1866 0xB*B8 | count*2); | 1872 0xB*B8 | count*2); |
1867 } | 1873 } |
1868 | 1874 |
1869 | 1875 |
1870 void Assembler::vstm(BlockAddrMode am, | 1876 void Assembler::vstm(BlockAddrMode am, |
1871 Register base, | 1877 Register base, |
1872 DwVfpRegister first, | 1878 DwVfpRegister first, |
1873 DwVfpRegister last, | 1879 DwVfpRegister last, |
1874 Condition cond) { | 1880 Condition cond) { |
1875 // Instruction details available in ARM DDI 0406A, A8-784. | 1881 // Instruction details available in ARM DDI 0406C.b, A8-1080. |
1876 // cond(31-28) | 110(27-25)| PUDW0(24-20) | Rbase(19-16) | | 1882 // cond(31-28) | 110(27-25)| PUDW0(24-20) | Rbase(19-16) | |
1877 // first(15-12) | 1011(11-8) | (count * 2) | 1883 // first(15-12) | 1011(11-8) | (count * 2) |
1878 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 1884 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
1879 ASSERT_LE(first.code(), last.code()); | 1885 ASSERT_LE(first.code(), last.code()); |
1880 ASSERT(am == ia || am == ia_w || am == db_w); | 1886 ASSERT(am == ia || am == ia_w || am == db_w); |
1881 ASSERT(!base.is(pc)); | 1887 ASSERT(!base.is(pc)); |
1882 | 1888 |
1883 int sd, d; | 1889 int sd, d; |
1884 first.split_code(&sd, &d); | 1890 first.split_code(&sd, &d); |
1885 int count = last.code() - first.code() + 1; | 1891 int count = last.code() - first.code() + 1; |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1985 *encoding |= (hi >> 12) & 0x80000; // Top bit of the high nybble. | 1991 *encoding |= (hi >> 12) & 0x80000; // Top bit of the high nybble. |
1986 | 1992 |
1987 return true; | 1993 return true; |
1988 } | 1994 } |
1989 | 1995 |
1990 | 1996 |
1991 void Assembler::vmov(const DwVfpRegister dst, | 1997 void Assembler::vmov(const DwVfpRegister dst, |
1992 double imm, | 1998 double imm, |
1993 const Register scratch, | 1999 const Register scratch, |
1994 const Condition cond) { | 2000 const Condition cond) { |
1995 // Dd = immediate | |
1996 // Instruction details available in ARM DDI 0406B, A8-640. | |
1997 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2001 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
1998 | 2002 |
1999 uint32_t enc; | 2003 uint32_t enc; |
2000 if (CpuFeatures::IsSupported(VFP3) && FitsVMOVDoubleImmediate(imm, &enc)) { | 2004 if (CpuFeatures::IsSupported(VFP3) && FitsVMOVDoubleImmediate(imm, &enc)) { |
2001 // The double can be encoded in the instruction. | 2005 // The double can be encoded in the instruction. |
2002 emit(cond | 0xE*B24 | 0xB*B20 | dst.code()*B12 | 0xB*B8 | enc); | 2006 |
2007 // Dd = immediate | |
2008 // Instruction details available in ARM DDI 0406C.b, A8-936. | |
2009 // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | imm4H(19-16) | | |
2010 // Vd(15-12) | 101(11-9) | sz=1(8) | imm4L(3-0) | |
2011 int vd, d; | |
2012 dst.split_code(&vd, &d); | |
2013 emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | vd*B12 | 0x5*B9 | B8 | enc); | |
2003 } else { | 2014 } else { |
2004 // Synthesise the double from ARM immediates. This could be implemented | 2015 // Synthesise the double from ARM immediates. This could be implemented |
2005 // using vldr from a constant pool. | 2016 // using vldr from a constant pool. |
2006 uint32_t lo, hi; | 2017 uint32_t lo, hi; |
2007 DoubleAsTwoUInt32(imm, &lo, &hi); | 2018 DoubleAsTwoUInt32(imm, &lo, &hi); |
2008 mov(ip, Operand(lo)); | 2019 mov(ip, Operand(lo)); |
2009 | 2020 |
2010 if (scratch.is(no_reg)) { | 2021 if (scratch.is(no_reg)) { |
2011 // Move the low part of the double into the lower of the corresponsing S | 2022 if (dst.code() < 16) { |
Rodolph Perfetta
2012/12/12 14:29:15
vmov.32 could also be used when dst.code() < 16. t
hans
2012/12/12 17:58:47
Done.
| |
2012 // registers of D register dst. | 2023 // Move the low part of the double into the lower of the corresponsing S |
2013 vmov(dst.low(), ip, cond); | 2024 // registers of D register dst. |
2025 vmov(dst.low(), ip, cond); | |
2014 | 2026 |
2015 // Move the high part of the double into the higher of the corresponsing S | 2027 // Move the high part of the double into the higher of the |
2016 // registers of D register dst. | 2028 // corresponsing S registers of D register dst. |
2017 mov(ip, Operand(hi)); | 2029 mov(ip, Operand(hi)); |
2018 vmov(dst.high(), ip, cond); | 2030 vmov(dst.high(), ip, cond); |
2031 } else { | |
2032 // There are no corresponding S registers for D register dst. | |
2033 | |
2034 // Move the low and high part separately using vmov.32. | |
2035 vmov(dst, 0, ip, cond); | |
2036 mov(ip, Operand(hi)); | |
2037 vmov(dst, 1, ip, cond); | |
2038 } | |
2019 } else { | 2039 } else { |
2020 // Move the low and high parts of the double to a D register in one | 2040 // Move the low and high parts of the double to a D register in one |
2021 // instruction. | 2041 // instruction. |
2022 mov(scratch, Operand(hi)); | 2042 mov(scratch, Operand(hi)); |
2023 vmov(dst, ip, scratch, cond); | 2043 vmov(dst, ip, scratch, cond); |
2024 } | 2044 } |
2025 } | 2045 } |
2026 } | 2046 } |
2027 | 2047 |
2028 | 2048 |
2029 void Assembler::vmov(const SwVfpRegister dst, | 2049 void Assembler::vmov(const SwVfpRegister dst, |
2030 const SwVfpRegister src, | 2050 const SwVfpRegister src, |
2031 const Condition cond) { | 2051 const Condition cond) { |
2032 // Sd = Sm | 2052 // Sd = Sm |
2033 // Instruction details available in ARM DDI 0406B, A8-642. | 2053 // Instruction details available in ARM DDI 0406B, A8-642. |
2034 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2054 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2035 int sd, d, sm, m; | 2055 int sd, d, sm, m; |
2036 dst.split_code(&sd, &d); | 2056 dst.split_code(&sd, &d); |
2037 src.split_code(&sm, &m); | 2057 src.split_code(&sm, &m); |
2038 emit(cond | 0xE*B24 | d*B22 | 0xB*B20 | sd*B12 | 0xA*B8 | B6 | m*B5 | sm); | 2058 emit(cond | 0xE*B24 | d*B22 | 0xB*B20 | sd*B12 | 0xA*B8 | B6 | m*B5 | sm); |
2039 } | 2059 } |
2040 | 2060 |
2041 | 2061 |
2042 void Assembler::vmov(const DwVfpRegister dst, | 2062 void Assembler::vmov(const DwVfpRegister dst, |
2043 const DwVfpRegister src, | 2063 const DwVfpRegister src, |
2044 const Condition cond) { | 2064 const Condition cond) { |
2045 // Dd = Dm | 2065 // Dd = Dm |
2046 // Instruction details available in ARM DDI 0406B, A8-642. | 2066 // Instruction details available in ARM DDI 0406C.b, A8-938. |
2067 // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0000(19-16) | Vd(15-12) | | |
2068 // 101(11-9) | sz=1(8) | 0(7) | 1(6) | M(5) | 0(4) | Vm(3-0) | |
2047 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2069 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2048 emit(cond | 0xE*B24 | 0xB*B20 | | 2070 int vd, d; |
2049 dst.code()*B12 | 0x5*B9 | B8 | B6 | src.code()); | 2071 dst.split_code(&vd, &d); |
2072 int vm, m; | |
2073 src.split_code(&vm, &m); | |
2074 emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | vd*B12 | 0x5*B9 | B8 | B6 | m*B5 | | |
2075 vm); | |
2050 } | 2076 } |
2051 | 2077 |
2052 | 2078 |
2079 void Assembler::vmov(const DwVfpRegister dst, | |
2080 int x, | |
2081 const Register src, | |
2082 const Condition cond) { | |
2083 // Dd[x] = Rt | |
2084 // Instruction details available in ARM DDI 0406C.b, A8-940. | |
2085 // cond(31-28) | 1110(27-24) | 0(23) | opc1=0X(22-21) | 0(20) | Vd(19-16) | | |
2086 // Rt(15-12) | 1011(11-8) | D(7) | opc2=00(6-5) | 1(4) | 0000(3-0) | |
2087 ASSERT(CpuFeatures::IsEnabled(VFP2)); | |
2088 ASSERT(x == 0 || x == 1); | |
2089 int vd, d; | |
2090 dst.split_code(&vd, &d); | |
2091 emit(cond | 0xE*B24 | x*B21 | vd*B16 | src.code()*B12 | 0xB*B8 | d*B7 | B4); | |
2092 } | |
2093 | |
2094 | |
2053 void Assembler::vmov(const DwVfpRegister dst, | 2095 void Assembler::vmov(const DwVfpRegister dst, |
2054 const Register src1, | 2096 const Register src1, |
2055 const Register src2, | 2097 const Register src2, |
2056 const Condition cond) { | 2098 const Condition cond) { |
2057 // Dm = <Rt,Rt2>. | 2099 // Dm = <Rt,Rt2>. |
2058 // Instruction details available in ARM DDI 0406A, A8-646. | 2100 // Instruction details available in ARM DDI 0406C.b, A8-948. |
2059 // cond(31-28) | 1100(27-24)| 010(23-21) | op=0(20) | Rt2(19-16) | | 2101 // cond(31-28) | 1100(27-24)| 010(23-21) | op=0(20) | Rt2(19-16) | |
2060 // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm | 2102 // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm |
2061 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2103 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2062 ASSERT(!src1.is(pc) && !src2.is(pc)); | 2104 ASSERT(!src1.is(pc) && !src2.is(pc)); |
2105 int vm, m; | |
2106 dst.split_code(&vm, &m); | |
2063 emit(cond | 0xC*B24 | B22 | src2.code()*B16 | | 2107 emit(cond | 0xC*B24 | B22 | src2.code()*B16 | |
2064 src1.code()*B12 | 0xB*B8 | B4 | dst.code()); | 2108 src1.code()*B12 | 0xB*B8 | m*B5 | B4 | vm); |
2065 } | 2109 } |
2066 | 2110 |
2067 | 2111 |
2068 void Assembler::vmov(const Register dst1, | 2112 void Assembler::vmov(const Register dst1, |
2069 const Register dst2, | 2113 const Register dst2, |
2070 const DwVfpRegister src, | 2114 const DwVfpRegister src, |
2071 const Condition cond) { | 2115 const Condition cond) { |
2072 // <Rt,Rt2> = Dm. | 2116 // <Rt,Rt2> = Dm. |
2073 // Instruction details available in ARM DDI 0406A, A8-646. | 2117 // Instruction details available in ARM DDI 0406C.b, A8-948. |
2074 // cond(31-28) | 1100(27-24)| 010(23-21) | op=1(20) | Rt2(19-16) | | 2118 // cond(31-28) | 1100(27-24)| 010(23-21) | op=1(20) | Rt2(19-16) | |
2075 // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm | 2119 // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm |
2076 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2120 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2077 ASSERT(!dst1.is(pc) && !dst2.is(pc)); | 2121 ASSERT(!dst1.is(pc) && !dst2.is(pc)); |
2122 int vm, m; | |
2123 src.split_code(&vm, &m); | |
2078 emit(cond | 0xC*B24 | B22 | B20 | dst2.code()*B16 | | 2124 emit(cond | 0xC*B24 | B22 | B20 | dst2.code()*B16 | |
2079 dst1.code()*B12 | 0xB*B8 | B4 | src.code()); | 2125 dst1.code()*B12 | 0xB*B8 | m*B5 | B4 | vm); |
2080 } | 2126 } |
2081 | 2127 |
2082 | 2128 |
2083 void Assembler::vmov(const SwVfpRegister dst, | 2129 void Assembler::vmov(const SwVfpRegister dst, |
2084 const Register src, | 2130 const Register src, |
2085 const Condition cond) { | 2131 const Condition cond) { |
2086 // Sn = Rt. | 2132 // Sn = Rt. |
2087 // Instruction details available in ARM DDI 0406A, A8-642. | 2133 // Instruction details available in ARM DDI 0406A, A8-642. |
2088 // cond(31-28) | 1110(27-24)| 000(23-21) | op=0(20) | Vn(19-16) | | 2134 // cond(31-28) | 1110(27-24)| 000(23-21) | op=0(20) | Vn(19-16) | |
2089 // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0) | 2135 // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0) |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2282 VFPConversionMode mode, | 2328 VFPConversionMode mode, |
2283 const Condition cond) { | 2329 const Condition cond) { |
2284 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2330 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2285 emit(EncodeVCVT(F32, dst.code(), F64, src.code(), mode, cond)); | 2331 emit(EncodeVCVT(F32, dst.code(), F64, src.code(), mode, cond)); |
2286 } | 2332 } |
2287 | 2333 |
2288 | 2334 |
2289 void Assembler::vneg(const DwVfpRegister dst, | 2335 void Assembler::vneg(const DwVfpRegister dst, |
2290 const DwVfpRegister src, | 2336 const DwVfpRegister src, |
2291 const Condition cond) { | 2337 const Condition cond) { |
2338 // Instruction details available in ARM DDI 0406C.b, A8-968. | |
2339 // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0001(19-16) | Vd(15-12) | | |
2340 // 101(11-9) | sz=1(8) | 0(7) | 1(6) | M(5) | 0(4) | Vm(3-0) | |
2292 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2341 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2293 emit(cond | 0xE*B24 | 0xB*B20 | B16 | dst.code()*B12 | | 2342 int vd, d; |
2294 0x5*B9 | B8 | B6 | src.code()); | 2343 dst.split_code(&vd, &d); |
2344 int vm, m; | |
2345 src.split_code(&vm, &m); | |
2346 | |
2347 emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | B16 | vd*B12 | 0x5*B9 | B8 | B6 | | |
2348 m*B5 | vm); | |
2295 } | 2349 } |
2296 | 2350 |
2297 | 2351 |
2298 void Assembler::vabs(const DwVfpRegister dst, | 2352 void Assembler::vabs(const DwVfpRegister dst, |
2299 const DwVfpRegister src, | 2353 const DwVfpRegister src, |
2300 const Condition cond) { | 2354 const Condition cond) { |
2355 // Instruction details available in ARM DDI 0406C.b, A8-524. | |
2356 // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0000(19-16) | Vd(15-12) | | |
2357 // 101(11-9) | sz=1(8) | 1(7) | 1(6) | M(5) | 0(4) | Vm(3-0) | |
2301 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2358 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2302 emit(cond | 0xE*B24 | 0xB*B20 | dst.code()*B12 | | 2359 int vd, d; |
2303 0x5*B9 | B8 | 0x3*B6 | src.code()); | 2360 dst.split_code(&vd, &d); |
2361 int vm, m; | |
2362 src.split_code(&vm, &m); | |
2363 emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | vd*B12 | 0x5*B9 | B8 | B7 | B6 | | |
2364 m*B5 | vm); | |
2304 } | 2365 } |
2305 | 2366 |
2306 | 2367 |
2307 void Assembler::vadd(const DwVfpRegister dst, | 2368 void Assembler::vadd(const DwVfpRegister dst, |
2308 const DwVfpRegister src1, | 2369 const DwVfpRegister src1, |
2309 const DwVfpRegister src2, | 2370 const DwVfpRegister src2, |
2310 const Condition cond) { | 2371 const Condition cond) { |
2311 // Dd = vadd(Dn, Dm) double precision floating point addition. | 2372 // Dd = vadd(Dn, Dm) double precision floating point addition. |
2312 // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. | 2373 // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. |
2313 // Instruction details available in ARM DDI 0406A, A8-536. | 2374 // Instruction details available in ARM DDI 0406C.b, A8-830. |
2314 // cond(31-28) | 11100(27-23)| D=?(22) | 11(21-20) | Vn(19-16) | | 2375 // cond(31-28) | 11100(27-23)| D(22) | 11(21-20) | Vn(19-16) | |
2315 // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 0(6) | M=?(5) | 0(4) | Vm(3-0) | 2376 // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0) |
2316 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2377 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2317 emit(cond | 0xE*B24 | 0x3*B20 | src1.code()*B16 | | 2378 int vd, d; |
2318 dst.code()*B12 | 0x5*B9 | B8 | src2.code()); | 2379 dst.split_code(&vd, &d); |
2380 int vn, n; | |
2381 src1.split_code(&vn, &n); | |
2382 int vm, m; | |
2383 src2.split_code(&vm, &m); | |
2384 emit(cond | 0x1C*B23 | d*B22 | 0x3*B20 | vn*B16 | vd*B12 | 0x5*B9 | B8 | | |
2385 n*B7 | m*B5 | vm); | |
2319 } | 2386 } |
2320 | 2387 |
2321 | 2388 |
2322 void Assembler::vsub(const DwVfpRegister dst, | 2389 void Assembler::vsub(const DwVfpRegister dst, |
2323 const DwVfpRegister src1, | 2390 const DwVfpRegister src1, |
2324 const DwVfpRegister src2, | 2391 const DwVfpRegister src2, |
2325 const Condition cond) { | 2392 const Condition cond) { |
2326 // Dd = vsub(Dn, Dm) double precision floating point subtraction. | 2393 // Dd = vsub(Dn, Dm) double precision floating point subtraction. |
2327 // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. | 2394 // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. |
2328 // Instruction details available in ARM DDI 0406A, A8-784. | 2395 // Instruction details available in ARM DDI 0406C.b, A8-1086. |
2329 // cond(31-28) | 11100(27-23)| D=?(22) | 11(21-20) | Vn(19-16) | | 2396 // cond(31-28) | 11100(27-23)| D(22) | 11(21-20) | Vn(19-16) | |
2330 // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 1(6) | M=?(5) | 0(4) | Vm(3-0) | 2397 // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 1(6) | M(5) | 0(4) | Vm(3-0) |
2331 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2398 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2332 emit(cond | 0xE*B24 | 0x3*B20 | src1.code()*B16 | | 2399 int vd, d; |
2333 dst.code()*B12 | 0x5*B9 | B8 | B6 | src2.code()); | 2400 dst.split_code(&vd, &d); |
2401 int vn, n; | |
2402 src1.split_code(&vn, &n); | |
2403 int vm, m; | |
2404 src2.split_code(&vm, &m); | |
2405 emit(cond | 0x1C*B23 | d*B22 | 0x3*B20 | vn*B16 | vd*B12 | 0x5*B9 | B8 | | |
2406 n*B7 | B6 | m*B5 | vm); | |
2334 } | 2407 } |
2335 | 2408 |
2336 | 2409 |
2337 void Assembler::vmul(const DwVfpRegister dst, | 2410 void Assembler::vmul(const DwVfpRegister dst, |
2338 const DwVfpRegister src1, | 2411 const DwVfpRegister src1, |
2339 const DwVfpRegister src2, | 2412 const DwVfpRegister src2, |
2340 const Condition cond) { | 2413 const Condition cond) { |
2341 // Dd = vmul(Dn, Dm) double precision floating point multiplication. | 2414 // Dd = vmul(Dn, Dm) double precision floating point multiplication. |
2342 // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. | 2415 // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. |
2343 // Instruction details available in ARM DDI 0406A, A8-784. | 2416 // Instruction details available in ARM DDI 0406C.b, A8-960. |
2344 // cond(31-28) | 11100(27-23)| D=?(22) | 10(21-20) | Vn(19-16) | | 2417 // cond(31-28) | 11100(27-23)| D(22) | 10(21-20) | Vn(19-16) | |
2345 // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 0(6) | M=?(5) | 0(4) | Vm(3-0) | 2418 // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0) |
2346 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2419 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2347 emit(cond | 0xE*B24 | 0x2*B20 | src1.code()*B16 | | 2420 int vd, d; |
2348 dst.code()*B12 | 0x5*B9 | B8 | src2.code()); | 2421 dst.split_code(&vd, &d); |
2422 int vn, n; | |
2423 src1.split_code(&vn, &n); | |
2424 int vm, m; | |
2425 src2.split_code(&vm, &m); | |
2426 emit(cond | 0x1C*B23 | d*B22 | 0x2*B20 | vn*B16 | vd*B12 | 0x5*B9 | B8 | | |
2427 n*B7 | m*B5 | vm); | |
2349 } | 2428 } |
2350 | 2429 |
2351 | 2430 |
2352 void Assembler::vmla(const DwVfpRegister dst, | 2431 void Assembler::vmla(const DwVfpRegister dst, |
2353 const DwVfpRegister src1, | 2432 const DwVfpRegister src1, |
2354 const DwVfpRegister src2, | 2433 const DwVfpRegister src2, |
2355 const Condition cond) { | 2434 const Condition cond) { |
2356 // Instruction details available in ARM DDI 0406C.b, A8-892. | 2435 // Instruction details available in ARM DDI 0406C.b, A8-932. |
2357 // cond(31-28) | 11100(27-23) | D=?(22) | 00(21-20) | Vn(19-16) | | 2436 // cond(31-28) | 11100(27-23) | D(22) | 00(21-20) | Vn(19-16) | |
2358 // Vd(15-12) | 101(11-9) | sz(8)=1 | N=?(7) | op(6)=0 | M=?(5) | 0(4) | | 2437 // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | op=0(6) | M(5) | 0(4) | Vm(3-0) |
2359 // Vm(3-0) | 2438 int vd, d; |
2360 unsigned x = (cond | 0x1C*B23 | src1.code()*B16 | | 2439 dst.split_code(&vd, &d); |
2361 dst.code()*B12 | 0x5*B9 | B8 | src2.code()); | 2440 int vn, n; |
2362 emit(x); | 2441 src1.split_code(&vn, &n); |
2442 int vm, m; | |
2443 src2.split_code(&vm, &m); | |
2444 emit(cond | 0x1C*B23 | d*B22 | vn*B16 | vd*B12 | 0x5*B9 | B8 | n*B7 | m*B5 | | |
2445 vm); | |
2363 } | 2446 } |
2364 | 2447 |
2365 | 2448 |
2366 void Assembler::vdiv(const DwVfpRegister dst, | 2449 void Assembler::vdiv(const DwVfpRegister dst, |
2367 const DwVfpRegister src1, | 2450 const DwVfpRegister src1, |
2368 const DwVfpRegister src2, | 2451 const DwVfpRegister src2, |
2369 const Condition cond) { | 2452 const Condition cond) { |
2370 // Dd = vdiv(Dn, Dm) double precision floating point division. | 2453 // Dd = vdiv(Dn, Dm) double precision floating point division. |
2371 // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. | 2454 // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. |
2372 // Instruction details available in ARM DDI 0406A, A8-584. | 2455 // Instruction details available in ARM DDI 0406C.b, A8-882. |
2373 // cond(31-28) | 11101(27-23)| D=?(22) | 00(21-20) | Vn(19-16) | | 2456 // cond(31-28) | 11101(27-23)| D(22) | 00(21-20) | Vn(19-16) | |
2374 // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=? | 0(6) | M=?(5) | 0(4) | Vm(3-0) | 2457 // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0) |
2375 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2458 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2376 emit(cond | 0xE*B24 | B23 | src1.code()*B16 | | 2459 int vd, d; |
2377 dst.code()*B12 | 0x5*B9 | B8 | src2.code()); | 2460 dst.split_code(&vd, &d); |
2461 int vn, n; | |
2462 src1.split_code(&vn, &n); | |
2463 int vm, m; | |
2464 src2.split_code(&vm, &m); | |
2465 emit(cond | 0x1D*B23 | d*B22 | vn*B16 | vd*B12 | 0x5*B9 | B8 | n*B7 | m*B5 | | |
2466 vm); | |
2378 } | 2467 } |
2379 | 2468 |
2380 | 2469 |
2381 void Assembler::vcmp(const DwVfpRegister src1, | 2470 void Assembler::vcmp(const DwVfpRegister src1, |
2382 const DwVfpRegister src2, | 2471 const DwVfpRegister src2, |
2383 const Condition cond) { | 2472 const Condition cond) { |
2384 // vcmp(Dd, Dm) double precision floating point comparison. | 2473 // vcmp(Dd, Dm) double precision floating point comparison. |
2385 // Instruction details available in ARM DDI 0406A, A8-570. | 2474 // Instruction details available in ARM DDI 0406C.b, A8-864. |
2386 // cond(31-28) | 11101 (27-23)| D=?(22) | 11 (21-20) | 0100 (19-16) | | 2475 // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0100(19-16) | |
2387 // Vd(15-12) | 101(11-9) | sz(8)=1 | E(7)=0 | 1(6) | M(5)=? | 0(4) | Vm(3-0) | 2476 // Vd(15-12) | 101(11-9) | sz=1(8) | E=0(7) | 1(6) | M(5) | 0(4) | Vm(3-0) |
2388 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2477 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2389 emit(cond | 0xE*B24 |B23 | 0x3*B20 | B18 | | 2478 int vd, d; |
2390 src1.code()*B12 | 0x5*B9 | B8 | B6 | src2.code()); | 2479 src1.split_code(&vd, &d); |
2480 int vm, m; | |
2481 src2.split_code(&vm, &m); | |
2482 emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | 0x4*B16 | vd*B12 | 0x5*B9 | B8 | B6 | | |
2483 m*B5 | vm); | |
2391 } | 2484 } |
2392 | 2485 |
2393 | 2486 |
2394 void Assembler::vcmp(const DwVfpRegister src1, | 2487 void Assembler::vcmp(const DwVfpRegister src1, |
2395 const double src2, | 2488 const double src2, |
2396 const Condition cond) { | 2489 const Condition cond) { |
2397 // vcmp(Dd, Dm) double precision floating point comparison. | 2490 // vcmp(Dd, #0.0) double precision floating point comparison. |
2398 // Instruction details available in ARM DDI 0406A, A8-570. | 2491 // Instruction details available in ARM DDI 0406C.b, A8-864. |
2399 // cond(31-28) | 11101 (27-23)| D=?(22) | 11 (21-20) | 0101 (19-16) | | 2492 // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0101(19-16) | |
2400 // Vd(15-12) | 101(11-9) | sz(8)=1 | E(7)=0 | 1(6) | M(5)=? | 0(4) | 0000(3-0) | 2493 // Vd(15-12) | 101(11-9) | sz=1(8) | E=0(7) | 1(6) | 0(5) | 0(4) | 0000(3-0) |
2401 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2494 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2402 ASSERT(src2 == 0.0); | 2495 ASSERT(src2 == 0.0); |
2403 emit(cond | 0xE*B24 |B23 | 0x3*B20 | B18 | B16 | | 2496 int vd, d; |
2404 src1.code()*B12 | 0x5*B9 | B8 | B6); | 2497 src1.split_code(&vd, &d); |
2498 emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | 0x5*B16 | vd*B12 | 0x5*B9 | B8 | B6); | |
2405 } | 2499 } |
2406 | 2500 |
2407 | 2501 |
2408 void Assembler::vmsr(Register dst, Condition cond) { | 2502 void Assembler::vmsr(Register dst, Condition cond) { |
2409 // Instruction details available in ARM DDI 0406A, A8-652. | 2503 // Instruction details available in ARM DDI 0406A, A8-652. |
2410 // cond(31-28) | 1110 (27-24) | 1110(23-20)| 0001 (19-16) | | 2504 // cond(31-28) | 1110 (27-24) | 1110(23-20)| 0001 (19-16) | |
2411 // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0) | 2505 // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0) |
2412 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2506 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2413 emit(cond | 0xE*B24 | 0xE*B20 | B16 | | 2507 emit(cond | 0xE*B24 | 0xE*B20 | B16 | |
2414 dst.code()*B12 | 0xA*B8 | B4); | 2508 dst.code()*B12 | 0xA*B8 | B4); |
2415 } | 2509 } |
2416 | 2510 |
2417 | 2511 |
2418 void Assembler::vmrs(Register dst, Condition cond) { | 2512 void Assembler::vmrs(Register dst, Condition cond) { |
2419 // Instruction details available in ARM DDI 0406A, A8-652. | 2513 // Instruction details available in ARM DDI 0406A, A8-652. |
2420 // cond(31-28) | 1110 (27-24) | 1111(23-20)| 0001 (19-16) | | 2514 // cond(31-28) | 1110 (27-24) | 1111(23-20)| 0001 (19-16) | |
2421 // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0) | 2515 // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0) |
2422 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2516 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2423 emit(cond | 0xE*B24 | 0xF*B20 | B16 | | 2517 emit(cond | 0xE*B24 | 0xF*B20 | B16 | |
2424 dst.code()*B12 | 0xA*B8 | B4); | 2518 dst.code()*B12 | 0xA*B8 | B4); |
2425 } | 2519 } |
2426 | 2520 |
2427 | 2521 |
2428 void Assembler::vsqrt(const DwVfpRegister dst, | 2522 void Assembler::vsqrt(const DwVfpRegister dst, |
2429 const DwVfpRegister src, | 2523 const DwVfpRegister src, |
2430 const Condition cond) { | 2524 const Condition cond) { |
2431 // cond(31-28) | 11101 (27-23)| D=?(22) | 11 (21-20) | 0001 (19-16) | | 2525 // Instruction details available in ARM DDI 0406C.b, A8-1058. |
2432 // Vd(15-12) | 101(11-9) | sz(8)=1 | 11 (7-6) | M(5)=? | 0(4) | Vm(3-0) | 2526 // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0001(19-16) | |
2527 // Vd(15-12) | 101(11-9) | sz=1(8) | 11(7-6) | M(5) | 0(4) | Vm(3-0) | |
2433 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2528 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2434 emit(cond | 0xE*B24 | B23 | 0x3*B20 | B16 | | 2529 int vd, d; |
2435 dst.code()*B12 | 0x5*B9 | B8 | 3*B6 | src.code()); | 2530 dst.split_code(&vd, &d); |
2531 int vm, m; | |
2532 src.split_code(&vm, &m); | |
2533 emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | B16 | vd*B12 | 0x5*B9 | B8 | 0x3*B6 | | |
2534 m*B5 | vm); | |
2436 } | 2535 } |
2437 | 2536 |
2438 | 2537 |
2439 // Pseudo instructions. | 2538 // Pseudo instructions. |
2440 void Assembler::nop(int type) { | 2539 void Assembler::nop(int type) { |
2441 // ARMv6{K/T2} and v7 have an actual NOP instruction but it serializes | 2540 // ARMv6{K/T2} and v7 have an actual NOP instruction but it serializes |
2442 // some of the CPU's pipeline and has to issue. Older ARM chips simply used | 2541 // some of the CPU's pipeline and has to issue. Older ARM chips simply used |
2443 // MOV Rx, Rx as NOP and it performs better even in newer CPUs. | 2542 // MOV Rx, Rx as NOP and it performs better even in newer CPUs. |
2444 // We therefore use MOV Rx, Rx, even on newer CPUs, and use Rx to encode | 2543 // We therefore use MOV Rx, Rx, even on newer CPUs, and use Rx to encode |
2445 // a type. | 2544 // a type. |
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2743 | 2842 |
2744 // Since a constant pool was just emitted, move the check offset forward by | 2843 // Since a constant pool was just emitted, move the check offset forward by |
2745 // the standard interval. | 2844 // the standard interval. |
2746 next_buffer_check_ = pc_offset() + kCheckPoolInterval; | 2845 next_buffer_check_ = pc_offset() + kCheckPoolInterval; |
2747 } | 2846 } |
2748 | 2847 |
2749 | 2848 |
2750 } } // namespace v8::internal | 2849 } } // namespace v8::internal |
2751 | 2850 |
2752 #endif // V8_TARGET_ARCH_ARM | 2851 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |