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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
44 namespace v8 { | 44 namespace v8 { |
45 namespace internal { | 45 namespace internal { |
46 | 46 |
47 #ifdef DEBUG | 47 #ifdef DEBUG |
48 bool CpuFeatures::initialized_ = false; | 48 bool CpuFeatures::initialized_ = false; |
49 #endif | 49 #endif |
50 unsigned CpuFeatures::supported_ = 0; | 50 unsigned CpuFeatures::supported_ = 0; |
51 unsigned CpuFeatures::found_by_runtime_probing_ = 0; | 51 unsigned CpuFeatures::found_by_runtime_probing_ = 0; |
52 | 52 |
53 | 53 |
| 54 ExternalReference ExternalReference::cpu_features() { |
| 55 ASSERT(CpuFeatures::initialized_); |
| 56 return ExternalReference(&CpuFeatures::supported_); |
| 57 } |
| 58 |
54 // Get the CPU features enabled by the build. For cross compilation the | 59 // Get the CPU features enabled by the build. For cross compilation the |
55 // preprocessor symbols CAN_USE_ARMV7_INSTRUCTIONS and CAN_USE_VFP3_INSTRUCTIONS | 60 // preprocessor symbols CAN_USE_ARMV7_INSTRUCTIONS and CAN_USE_VFP3_INSTRUCTIONS |
56 // can be defined to enable ARMv7 and VFPv3 instructions when building the | 61 // can be defined to enable ARMv7 and VFPv3 instructions when building the |
57 // snapshot. | 62 // snapshot. |
58 static unsigned CpuFeaturesImpliedByCompiler() { | 63 static unsigned CpuFeaturesImpliedByCompiler() { |
59 unsigned answer = 0; | 64 unsigned answer = 0; |
60 #ifdef CAN_USE_ARMV7_INSTRUCTIONS | 65 #ifdef CAN_USE_ARMV7_INSTRUCTIONS |
61 answer |= 1u << ARMv7; | 66 answer |= 1u << ARMv7; |
62 #endif // CAN_USE_ARMV7_INSTRUCTIONS | 67 #endif // CAN_USE_ARMV7_INSTRUCTIONS |
63 #ifdef CAN_USE_VFP3_INSTRUCTIONS | 68 #ifdef CAN_USE_VFP3_INSTRUCTIONS |
64 answer |= 1u << VFP3 | 1u << VFP2 | 1u << ARMv7; | 69 answer |= 1u << VFP3 | 1u << VFP2 | 1u << ARMv7; |
65 #endif // CAN_USE_VFP3_INSTRUCTIONS | 70 #endif // CAN_USE_VFP3_INSTRUCTIONS |
66 #ifdef CAN_USE_VFP2_INSTRUCTIONS | 71 #ifdef CAN_USE_VFP2_INSTRUCTIONS |
67 answer |= 1u << VFP2; | 72 answer |= 1u << VFP2; |
68 #endif // CAN_USE_VFP2_INSTRUCTIONS | 73 #endif // CAN_USE_VFP2_INSTRUCTIONS |
| 74 #ifdef CAN_USE_VFP32DREGS |
| 75 answer |= 1u << VFP32DREGS; |
| 76 #endif // CAN_USE_VFP32DREGS |
69 | 77 |
70 #ifdef __arm__ | 78 #ifdef __arm__ |
71 // If the compiler is allowed to use VFP then we can use VFP too in our code | 79 // If the compiler is allowed to use VFP then we can use VFP too in our code |
72 // generation even when generating snapshots. ARMv7 and hardware floating | 80 // generation even when generating snapshots. ARMv7 and hardware floating |
73 // point support implies VFPv3, see ARM DDI 0406B, page A1-6. | 81 // point support implies VFPv3, see ARM DDI 0406B, page A1-6. |
74 #if defined(CAN_USE_ARMV7_INSTRUCTIONS) && defined(__VFP_FP__) \ | 82 #if defined(CAN_USE_ARMV7_INSTRUCTIONS) && defined(__VFP_FP__) \ |
75 && !defined(__SOFTFP__) | 83 && !defined(__SOFTFP__) |
76 answer |= 1u << VFP3 | 1u << ARMv7 | 1u << VFP2; | 84 answer |= 1u << VFP3 | 1u << ARMv7 | 1u << VFP2; |
77 #endif // defined(CAN_USE_ARMV7_INSTRUCTIONS) && defined(__VFP_FP__) | 85 #endif // defined(CAN_USE_ARMV7_INSTRUCTIONS) && defined(__VFP_FP__) |
78 // && !defined(__SOFTFP__) | 86 // && !defined(__SOFTFP__) |
79 #endif // _arm__ | 87 #endif // _arm__ |
80 if (answer & (1u << ARMv7)) { | 88 if (answer & (1u << ARMv7)) { |
81 answer |= 1u << UNALIGNED_ACCESSES; | 89 answer |= 1u << UNALIGNED_ACCESSES; |
82 } | 90 } |
83 | 91 |
84 return answer; | 92 return answer; |
85 } | 93 } |
86 | 94 |
87 | 95 |
88 const char* DwVfpRegister::AllocationIndexToString(int index) { | 96 const char* DwVfpRegister::AllocationIndexToString(int index) { |
89 if (CpuFeatures::IsSupported(VFP2)) { | 97 if (CpuFeatures::IsSupported(VFP2)) { |
90 ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters); | 98 ASSERT(index >= 0 && index < NumAllocatableRegisters()); |
| 99 ASSERT(kScratchDoubleReg.code() - kDoubleRegZero.code() == |
| 100 kNumReservedRegisters - 1); |
| 101 if (index >= kDoubleRegZero.code()) |
| 102 index += kNumReservedRegisters; |
| 103 |
| 104 // TODO(hans): Maybe this could just use VFPRegisters::Name()? |
91 const char* const names[] = { | 105 const char* const names[] = { |
92 "d0", | 106 "d0", |
93 "d1", | 107 "d1", |
94 "d2", | 108 "d2", |
95 "d3", | 109 "d3", |
96 "d4", | 110 "d4", |
97 "d5", | 111 "d5", |
98 "d6", | 112 "d6", |
99 "d7", | 113 "d7", |
100 "d8", | 114 "d8", |
101 "d9", | 115 "d9", |
102 "d10", | 116 "d10", |
103 "d11", | 117 "d11", |
104 "d12", | 118 "d12", |
105 "d13" | 119 "d13" |
| 120 "d14", |
| 121 "d15", |
| 122 "d16", |
| 123 "d17", |
| 124 "d18", |
| 125 "d19", |
| 126 "d20", |
| 127 "d21", |
| 128 "d22", |
| 129 "d23", |
| 130 "d24", |
| 131 "d25", |
| 132 "d26", |
| 133 "d27", |
| 134 "d28", |
| 135 "d29", |
| 136 "d30", |
| 137 "d31" |
106 }; | 138 }; |
107 return names[index]; | 139 return names[index]; |
108 } else { | 140 } else { |
109 ASSERT(index == 0); | 141 ASSERT(index == 0); |
110 return "sfpd0"; | 142 return "sfpd0"; |
111 } | 143 } |
112 } | 144 } |
113 | 145 |
114 | 146 |
115 void CpuFeatures::Probe() { | 147 void CpuFeatures::Probe() { |
(...skipping 25 matching lines...) Expand all Loading... |
141 supported_ |= 1u << ARMv7; | 173 supported_ |= 1u << ARMv7; |
142 } | 174 } |
143 | 175 |
144 if (FLAG_enable_sudiv) { | 176 if (FLAG_enable_sudiv) { |
145 supported_ |= 1u << SUDIV; | 177 supported_ |= 1u << SUDIV; |
146 } | 178 } |
147 | 179 |
148 if (FLAG_enable_movw_movt) { | 180 if (FLAG_enable_movw_movt) { |
149 supported_ |= 1u << MOVW_MOVT_IMMEDIATE_LOADS; | 181 supported_ |= 1u << MOVW_MOVT_IMMEDIATE_LOADS; |
150 } | 182 } |
| 183 |
| 184 if (FLAG_enable_32dregs) { |
| 185 supported_ |= 1u << VFP32DREGS; |
| 186 } |
| 187 |
151 #else // __arm__ | 188 #else // __arm__ |
152 // Probe for additional features not already known to be available. | 189 // Probe for additional features not already known to be available. |
153 if (!IsSupported(VFP3) && OS::ArmCpuHasFeature(VFP3)) { | 190 if (!IsSupported(VFP3) && OS::ArmCpuHasFeature(VFP3)) { |
154 // This implementation also sets the VFP flags if runtime | 191 // This implementation also sets the VFP flags if runtime |
155 // detection of VFP returns true. VFPv3 implies ARMv7 and VFP2, see ARM DDI | 192 // detection of VFP returns true. VFPv3 implies ARMv7 and VFP2, see ARM DDI |
156 // 0406B, page A1-6. | 193 // 0406B, page A1-6. |
157 found_by_runtime_probing_ |= 1u << VFP3 | 1u << ARMv7 | 1u << VFP2; | 194 found_by_runtime_probing_ |= 1u << VFP3 | 1u << ARMv7 | 1u << VFP2; |
158 } else if (!IsSupported(VFP2) && OS::ArmCpuHasFeature(VFP2)) { | 195 } else if (!IsSupported(VFP2) && OS::ArmCpuHasFeature(VFP2)) { |
159 found_by_runtime_probing_ |= 1u << VFP2; | 196 found_by_runtime_probing_ |= 1u << VFP2; |
160 } | 197 } |
161 | 198 |
162 if (!IsSupported(ARMv7) && OS::ArmCpuHasFeature(ARMv7)) { | 199 if (!IsSupported(ARMv7) && OS::ArmCpuHasFeature(ARMv7)) { |
163 found_by_runtime_probing_ |= 1u << ARMv7; | 200 found_by_runtime_probing_ |= 1u << ARMv7; |
164 } | 201 } |
165 | 202 |
166 if (!IsSupported(SUDIV) && OS::ArmCpuHasFeature(SUDIV)) { | 203 if (!IsSupported(SUDIV) && OS::ArmCpuHasFeature(SUDIV)) { |
167 found_by_runtime_probing_ |= 1u << SUDIV; | 204 found_by_runtime_probing_ |= 1u << SUDIV; |
168 } | 205 } |
169 | 206 |
170 if (!IsSupported(UNALIGNED_ACCESSES) && OS::ArmCpuHasFeature(ARMv7)) { | 207 if (!IsSupported(UNALIGNED_ACCESSES) && OS::ArmCpuHasFeature(ARMv7)) { |
171 found_by_runtime_probing_ |= 1u << UNALIGNED_ACCESSES; | 208 found_by_runtime_probing_ |= 1u << UNALIGNED_ACCESSES; |
172 } | 209 } |
173 | 210 |
174 if (OS::GetCpuImplementer() == QUALCOMM_IMPLEMENTER && | 211 if (OS::GetCpuImplementer() == QUALCOMM_IMPLEMENTER && |
175 OS::ArmCpuHasFeature(ARMv7)) { | 212 OS::ArmCpuHasFeature(ARMv7)) { |
176 found_by_runtime_probing_ |= 1u << MOVW_MOVT_IMMEDIATE_LOADS; | 213 found_by_runtime_probing_ |= 1u << MOVW_MOVT_IMMEDIATE_LOADS; |
177 } | 214 } |
178 | 215 |
| 216 if (!IsSupported(VFP32DREGS) && OS::ArmCpuHasFeature(VFP32DREGS)) { |
| 217 found_by_runtime_probing_ |= 1u << VFP32DREGS; |
| 218 } |
| 219 |
179 supported_ |= found_by_runtime_probing_; | 220 supported_ |= found_by_runtime_probing_; |
180 #endif | 221 #endif |
181 | 222 |
182 // Assert that VFP3 implies VFP2 and ARMv7. | 223 // Assert that VFP3 implies VFP2 and ARMv7. |
183 ASSERT(!IsSupported(VFP3) || (IsSupported(VFP2) && IsSupported(ARMv7))); | 224 ASSERT(!IsSupported(VFP3) || (IsSupported(VFP2) && IsSupported(ARMv7))); |
184 } | 225 } |
185 | 226 |
186 | 227 |
187 // ----------------------------------------------------------------------------- | 228 // ----------------------------------------------------------------------------- |
188 // Implementation of RelocInfo | 229 // Implementation of RelocInfo |
(...skipping 1550 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1739 } | 1780 } |
1740 | 1781 |
1741 | 1782 |
1742 // Support for VFP. | 1783 // Support for VFP. |
1743 | 1784 |
1744 void Assembler::vldr(const DwVfpRegister dst, | 1785 void Assembler::vldr(const DwVfpRegister dst, |
1745 const Register base, | 1786 const Register base, |
1746 int offset, | 1787 int offset, |
1747 const Condition cond) { | 1788 const Condition cond) { |
1748 // Ddst = MEM(Rbase + offset). | 1789 // Ddst = MEM(Rbase + offset). |
1749 // Instruction details available in ARM DDI 0406A, A8-628. | 1790 // Instruction details available in ARM DDI 0406C.b, A8-924. |
1750 // cond(31-28) | 1101(27-24)| U001(23-20) | Rbase(19-16) | | 1791 // cond(31-28) | 1101(27-24)| U(23) | D(22) | 01(21-20) | Rbase(19-16) | |
1751 // Vdst(15-12) | 1011(11-8) | offset | 1792 // Vd(15-12) | 1011(11-8) | offset |
1752 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 1793 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
1753 int u = 1; | 1794 int u = 1; |
1754 if (offset < 0) { | 1795 if (offset < 0) { |
1755 offset = -offset; | 1796 offset = -offset; |
1756 u = 0; | 1797 u = 0; |
1757 } | 1798 } |
| 1799 int vd, d; |
| 1800 dst.split_code(&vd, &d); |
1758 | 1801 |
1759 ASSERT(offset >= 0); | 1802 ASSERT(offset >= 0); |
1760 if ((offset % 4) == 0 && (offset / 4) < 256) { | 1803 if ((offset % 4) == 0 && (offset / 4) < 256) { |
1761 emit(cond | u*B23 | 0xD1*B20 | base.code()*B16 | dst.code()*B12 | | 1804 emit(cond | 0xD*B24 | u*B23 | d*B22 | B20 | base.code()*B16 | vd*B12 | |
1762 0xB*B8 | ((offset / 4) & 255)); | 1805 0xB*B8 | ((offset / 4) & 255)); |
1763 } else { | 1806 } else { |
1764 // Larger offsets must be handled by computing the correct address | 1807 // Larger offsets must be handled by computing the correct address |
1765 // in the ip register. | 1808 // in the ip register. |
1766 ASSERT(!base.is(ip)); | 1809 ASSERT(!base.is(ip)); |
1767 if (u == 1) { | 1810 if (u == 1) { |
1768 add(ip, base, Operand(offset)); | 1811 add(ip, base, Operand(offset)); |
1769 } else { | 1812 } else { |
1770 sub(ip, base, Operand(offset)); | 1813 sub(ip, base, Operand(offset)); |
1771 } | 1814 } |
1772 emit(cond | 0xD1*B20 | ip.code()*B16 | dst.code()*B12 | 0xB*B8); | 1815 emit(cond | 0xD*B24 | d*B22 | B20 | ip.code()*B16 | vd*B12 | 0xB*B8); |
1773 } | 1816 } |
1774 } | 1817 } |
1775 | 1818 |
1776 | 1819 |
1777 void Assembler::vldr(const DwVfpRegister dst, | 1820 void Assembler::vldr(const DwVfpRegister dst, |
1778 const MemOperand& operand, | 1821 const MemOperand& operand, |
1779 const Condition cond) { | 1822 const Condition cond) { |
1780 ASSERT(!operand.rm().is_valid()); | 1823 ASSERT(!operand.rm().is_valid()); |
1781 ASSERT(operand.am_ == Offset); | 1824 ASSERT(operand.am_ == Offset); |
1782 vldr(dst, operand.rn(), operand.offset(), cond); | 1825 vldr(dst, operand.rn(), operand.offset(), cond); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1825 ASSERT(operand.am_ == Offset); | 1868 ASSERT(operand.am_ == Offset); |
1826 vldr(dst, operand.rn(), operand.offset(), cond); | 1869 vldr(dst, operand.rn(), operand.offset(), cond); |
1827 } | 1870 } |
1828 | 1871 |
1829 | 1872 |
1830 void Assembler::vstr(const DwVfpRegister src, | 1873 void Assembler::vstr(const DwVfpRegister src, |
1831 const Register base, | 1874 const Register base, |
1832 int offset, | 1875 int offset, |
1833 const Condition cond) { | 1876 const Condition cond) { |
1834 // MEM(Rbase + offset) = Dsrc. | 1877 // MEM(Rbase + offset) = Dsrc. |
1835 // Instruction details available in ARM DDI 0406A, A8-786. | 1878 // Instruction details available in ARM DDI 0406C.b, A8-1082. |
1836 // cond(31-28) | 1101(27-24)| U000(23-20) | | Rbase(19-16) | | 1879 // cond(31-28) | 1101(27-24)| U(23) | D(22) | 00(21-20) | Rbase(19-16) | |
1837 // Vsrc(15-12) | 1011(11-8) | (offset/4) | 1880 // Vd(15-12) | 1011(11-8) | (offset/4) |
1838 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 1881 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
1839 int u = 1; | 1882 int u = 1; |
1840 if (offset < 0) { | 1883 if (offset < 0) { |
1841 offset = -offset; | 1884 offset = -offset; |
1842 u = 0; | 1885 u = 0; |
1843 } | 1886 } |
1844 ASSERT(offset >= 0); | 1887 ASSERT(offset >= 0); |
| 1888 int vd, d; |
| 1889 src.split_code(&vd, &d); |
| 1890 |
1845 if ((offset % 4) == 0 && (offset / 4) < 256) { | 1891 if ((offset % 4) == 0 && (offset / 4) < 256) { |
1846 emit(cond | u*B23 | 0xD0*B20 | base.code()*B16 | src.code()*B12 | | 1892 emit(cond | 0xD*B24 | u*B23 | d*B22 | base.code()*B16 | vd*B12 | 0xB*B8 | |
1847 0xB*B8 | ((offset / 4) & 255)); | 1893 ((offset / 4) & 255)); |
1848 } else { | 1894 } else { |
1849 // Larger offsets must be handled by computing the correct address | 1895 // Larger offsets must be handled by computing the correct address |
1850 // in the ip register. | 1896 // in the ip register. |
1851 ASSERT(!base.is(ip)); | 1897 ASSERT(!base.is(ip)); |
1852 if (u == 1) { | 1898 if (u == 1) { |
1853 add(ip, base, Operand(offset)); | 1899 add(ip, base, Operand(offset)); |
1854 } else { | 1900 } else { |
1855 sub(ip, base, Operand(offset)); | 1901 sub(ip, base, Operand(offset)); |
1856 } | 1902 } |
1857 emit(cond | 0xD0*B20 | ip.code()*B16 | src.code()*B12 | 0xB*B8); | 1903 emit(cond | 0xD*B24 | d*B22 | ip.code()*B16 | vd*B12 | 0xB*B8); |
1858 } | 1904 } |
1859 } | 1905 } |
1860 | 1906 |
1861 | 1907 |
1862 void Assembler::vstr(const DwVfpRegister src, | 1908 void Assembler::vstr(const DwVfpRegister src, |
1863 const MemOperand& operand, | 1909 const MemOperand& operand, |
1864 const Condition cond) { | 1910 const Condition cond) { |
1865 ASSERT(!operand.rm().is_valid()); | 1911 ASSERT(!operand.rm().is_valid()); |
1866 ASSERT(operand.am_ == Offset); | 1912 ASSERT(operand.am_ == Offset); |
1867 vstr(src, operand.rn(), operand.offset(), cond); | 1913 vstr(src, operand.rn(), operand.offset(), cond); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1909 ASSERT(operand.am_ == Offset); | 1955 ASSERT(operand.am_ == Offset); |
1910 vstr(src, operand.rn(), operand.offset(), cond); | 1956 vstr(src, operand.rn(), operand.offset(), cond); |
1911 } | 1957 } |
1912 | 1958 |
1913 | 1959 |
1914 void Assembler::vldm(BlockAddrMode am, | 1960 void Assembler::vldm(BlockAddrMode am, |
1915 Register base, | 1961 Register base, |
1916 DwVfpRegister first, | 1962 DwVfpRegister first, |
1917 DwVfpRegister last, | 1963 DwVfpRegister last, |
1918 Condition cond) { | 1964 Condition cond) { |
1919 // Instruction details available in ARM DDI 0406A, A8-626. | 1965 // Instruction details available in ARM DDI 0406C.b, A8-922. |
1920 // cond(31-28) | 110(27-25)| PUDW1(24-20) | Rbase(19-16) | | 1966 // cond(31-28) | 110(27-25)| PUDW1(24-20) | Rbase(19-16) | |
1921 // first(15-12) | 1010(11-8) | (count * 2) | 1967 // first(15-12) | 1011(11-8) | (count * 2) |
1922 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 1968 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
1923 ASSERT_LE(first.code(), last.code()); | 1969 ASSERT_LE(first.code(), last.code()); |
1924 ASSERT(am == ia || am == ia_w || am == db_w); | 1970 ASSERT(am == ia || am == ia_w || am == db_w); |
1925 ASSERT(!base.is(pc)); | 1971 ASSERT(!base.is(pc)); |
1926 | 1972 |
1927 int sd, d; | 1973 int sd, d; |
1928 first.split_code(&sd, &d); | 1974 first.split_code(&sd, &d); |
1929 int count = last.code() - first.code() + 1; | 1975 int count = last.code() - first.code() + 1; |
1930 ASSERT(count <= 16); | 1976 ASSERT(count <= 16); |
1931 emit(cond | B27 | B26 | am | d*B22 | B20 | base.code()*B16 | sd*B12 | | 1977 emit(cond | B27 | B26 | am | d*B22 | B20 | base.code()*B16 | sd*B12 | |
1932 0xB*B8 | count*2); | 1978 0xB*B8 | count*2); |
1933 } | 1979 } |
1934 | 1980 |
1935 | 1981 |
1936 void Assembler::vstm(BlockAddrMode am, | 1982 void Assembler::vstm(BlockAddrMode am, |
1937 Register base, | 1983 Register base, |
1938 DwVfpRegister first, | 1984 DwVfpRegister first, |
1939 DwVfpRegister last, | 1985 DwVfpRegister last, |
1940 Condition cond) { | 1986 Condition cond) { |
1941 // Instruction details available in ARM DDI 0406A, A8-784. | 1987 // Instruction details available in ARM DDI 0406C.b, A8-1080. |
1942 // cond(31-28) | 110(27-25)| PUDW0(24-20) | Rbase(19-16) | | 1988 // cond(31-28) | 110(27-25)| PUDW0(24-20) | Rbase(19-16) | |
1943 // first(15-12) | 1011(11-8) | (count * 2) | 1989 // first(15-12) | 1011(11-8) | (count * 2) |
1944 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 1990 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
1945 ASSERT_LE(first.code(), last.code()); | 1991 ASSERT_LE(first.code(), last.code()); |
1946 ASSERT(am == ia || am == ia_w || am == db_w); | 1992 ASSERT(am == ia || am == ia_w || am == db_w); |
1947 ASSERT(!base.is(pc)); | 1993 ASSERT(!base.is(pc)); |
1948 | 1994 |
1949 int sd, d; | 1995 int sd, d; |
1950 first.split_code(&sd, &d); | 1996 first.split_code(&sd, &d); |
1951 int count = last.code() - first.code() + 1; | 1997 int count = last.code() - first.code() + 1; |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2051 *encoding |= (hi >> 12) & 0x80000; // Top bit of the high nybble. | 2097 *encoding |= (hi >> 12) & 0x80000; // Top bit of the high nybble. |
2052 | 2098 |
2053 return true; | 2099 return true; |
2054 } | 2100 } |
2055 | 2101 |
2056 | 2102 |
2057 void Assembler::vmov(const DwVfpRegister dst, | 2103 void Assembler::vmov(const DwVfpRegister dst, |
2058 double imm, | 2104 double imm, |
2059 const Register scratch, | 2105 const Register scratch, |
2060 const Condition cond) { | 2106 const Condition cond) { |
2061 // Dd = immediate | |
2062 // Instruction details available in ARM DDI 0406B, A8-640. | |
2063 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2107 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2064 | 2108 |
2065 uint32_t enc; | 2109 uint32_t enc; |
2066 if (CpuFeatures::IsSupported(VFP3) && FitsVMOVDoubleImmediate(imm, &enc)) { | 2110 if (CpuFeatures::IsSupported(VFP3) && FitsVMOVDoubleImmediate(imm, &enc)) { |
2067 // The double can be encoded in the instruction. | 2111 // The double can be encoded in the instruction. |
2068 emit(cond | 0xE*B24 | 0xB*B20 | dst.code()*B12 | 0xB*B8 | enc); | 2112 // |
| 2113 // Dd = immediate |
| 2114 // Instruction details available in ARM DDI 0406C.b, A8-936. |
| 2115 // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | imm4H(19-16) | |
| 2116 // Vd(15-12) | 101(11-9) | sz=1(8) | imm4L(3-0) |
| 2117 int vd, d; |
| 2118 dst.split_code(&vd, &d); |
| 2119 emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | vd*B12 | 0x5*B9 | B8 | enc); |
2069 } else if (FLAG_enable_vldr_imm) { | 2120 } else if (FLAG_enable_vldr_imm) { |
2070 // TODO(jfb) Temporarily turned off until we have constant blinding or | 2121 // TODO(jfb) Temporarily turned off until we have constant blinding or |
2071 // some equivalent mitigation: an attacker can otherwise control | 2122 // some equivalent mitigation: an attacker can otherwise control |
2072 // generated data which also happens to be executable, a Very Bad | 2123 // generated data which also happens to be executable, a Very Bad |
2073 // Thing indeed. | 2124 // Thing indeed. |
2074 // Blinding gets tricky because we don't have xor, we probably | 2125 // Blinding gets tricky because we don't have xor, we probably |
2075 // need to add/subtract without losing precision, which requires a | 2126 // need to add/subtract without losing precision, which requires a |
2076 // cookie value that Lithium is probably better positioned to | 2127 // cookie value that Lithium is probably better positioned to |
2077 // choose. | 2128 // choose. |
2078 // We could also add a few peepholes here like detecting 0.0 and | 2129 // We could also add a few peepholes here like detecting 0.0 and |
2079 // -0.0 and doing a vmov from the sequestered d14, forcing denorms | 2130 // -0.0 and doing a vmov from the sequestered d14, forcing denorms |
2080 // to zero (we set flush-to-zero), and normalizing NaN values. | 2131 // to zero (we set flush-to-zero), and normalizing NaN values. |
2081 // We could also detect redundant values. | 2132 // We could also detect redundant values. |
2082 // The code could also randomize the order of values, though | 2133 // The code could also randomize the order of values, though |
2083 // that's tricky because vldr has a limited reach. Furthermore | 2134 // that's tricky because vldr has a limited reach. Furthermore |
2084 // it breaks load locality. | 2135 // it breaks load locality. |
2085 RecordRelocInfo(imm); | 2136 RecordRelocInfo(imm); |
2086 vldr(dst, MemOperand(pc, 0), cond); | 2137 vldr(dst, MemOperand(pc, 0), cond); |
2087 } else { | 2138 } else { |
2088 // Synthesise the double from ARM immediates. | 2139 // Synthesise the double from ARM immediates. |
2089 uint32_t lo, hi; | 2140 uint32_t lo, hi; |
2090 DoubleAsTwoUInt32(imm, &lo, &hi); | 2141 DoubleAsTwoUInt32(imm, &lo, &hi); |
2091 mov(ip, Operand(lo)); | |
2092 | 2142 |
2093 if (scratch.is(no_reg)) { | 2143 if (scratch.is(no_reg)) { |
2094 // Move the low part of the double into the lower of the corresponsing S | 2144 if (dst.code() < 16) { |
2095 // registers of D register dst. | 2145 // Move the low part of the double into the lower of the corresponsing S |
2096 vmov(dst.low(), ip, cond); | 2146 // registers of D register dst. |
| 2147 mov(ip, Operand(lo)); |
| 2148 vmov(dst.low(), ip, cond); |
2097 | 2149 |
2098 // Move the high part of the double into the higher of the corresponsing S | 2150 // Move the high part of the double into the higher of the |
2099 // registers of D register dst. | 2151 // corresponsing S registers of D register dst. |
2100 mov(ip, Operand(hi)); | 2152 mov(ip, Operand(hi)); |
2101 vmov(dst.high(), ip, cond); | 2153 vmov(dst.high(), ip, cond); |
| 2154 } else { |
| 2155 // D16-D31 does not have S registers, so move the low and high parts |
| 2156 // directly to the D register using vmov.32. |
| 2157 // Note: This may be slower, so we only do this when we have to. |
| 2158 mov(ip, Operand(lo)); |
| 2159 vmov(dst, 0, ip, cond); |
| 2160 mov(ip, Operand(hi)); |
| 2161 vmov(dst, 1, ip, cond); |
| 2162 } |
2102 } else { | 2163 } else { |
2103 // Move the low and high parts of the double to a D register in one | 2164 // Move the low and high parts of the double to a D register in one |
2104 // instruction. | 2165 // instruction. |
| 2166 mov(ip, Operand(lo)); |
2105 mov(scratch, Operand(hi)); | 2167 mov(scratch, Operand(hi)); |
2106 vmov(dst, ip, scratch, cond); | 2168 vmov(dst, ip, scratch, cond); |
2107 } | 2169 } |
2108 } | 2170 } |
2109 } | 2171 } |
2110 | 2172 |
2111 | 2173 |
2112 void Assembler::vmov(const SwVfpRegister dst, | 2174 void Assembler::vmov(const SwVfpRegister dst, |
2113 const SwVfpRegister src, | 2175 const SwVfpRegister src, |
2114 const Condition cond) { | 2176 const Condition cond) { |
2115 // Sd = Sm | 2177 // Sd = Sm |
2116 // Instruction details available in ARM DDI 0406B, A8-642. | 2178 // Instruction details available in ARM DDI 0406B, A8-642. |
2117 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2179 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2118 int sd, d, sm, m; | 2180 int sd, d, sm, m; |
2119 dst.split_code(&sd, &d); | 2181 dst.split_code(&sd, &d); |
2120 src.split_code(&sm, &m); | 2182 src.split_code(&sm, &m); |
2121 emit(cond | 0xE*B24 | d*B22 | 0xB*B20 | sd*B12 | 0xA*B8 | B6 | m*B5 | sm); | 2183 emit(cond | 0xE*B24 | d*B22 | 0xB*B20 | sd*B12 | 0xA*B8 | B6 | m*B5 | sm); |
2122 } | 2184 } |
2123 | 2185 |
2124 | 2186 |
2125 void Assembler::vmov(const DwVfpRegister dst, | 2187 void Assembler::vmov(const DwVfpRegister dst, |
2126 const DwVfpRegister src, | 2188 const DwVfpRegister src, |
2127 const Condition cond) { | 2189 const Condition cond) { |
2128 // Dd = Dm | 2190 // Dd = Dm |
2129 // Instruction details available in ARM DDI 0406B, A8-642. | 2191 // Instruction details available in ARM DDI 0406C.b, A8-938. |
| 2192 // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0000(19-16) | Vd(15-12) | |
| 2193 // 101(11-9) | sz=1(8) | 0(7) | 1(6) | M(5) | 0(4) | Vm(3-0) |
2130 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2194 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2131 emit(cond | 0xE*B24 | 0xB*B20 | | 2195 int vd, d; |
2132 dst.code()*B12 | 0x5*B9 | B8 | B6 | src.code()); | 2196 dst.split_code(&vd, &d); |
| 2197 int vm, m; |
| 2198 src.split_code(&vm, &m); |
| 2199 emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | vd*B12 | 0x5*B9 | B8 | B6 | m*B5 | |
| 2200 vm); |
2133 } | 2201 } |
2134 | 2202 |
2135 | 2203 |
| 2204 void Assembler::vmov(const DwVfpRegister dst, |
| 2205 int index, |
| 2206 const Register src, |
| 2207 const Condition cond) { |
| 2208 // Dd[index] = Rt |
| 2209 // Instruction details available in ARM DDI 0406C.b, A8-940. |
| 2210 // cond(31-28) | 1110(27-24) | 0(23) | opc1=0index(22-21) | 0(20) | |
| 2211 // Vd(19-16) | Rt(15-12) | 1011(11-8) | D(7) | opc2=00(6-5) | 1(4) | 0000(3-0) |
| 2212 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
| 2213 ASSERT(index == 0 || index == 1); |
| 2214 int vd, d; |
| 2215 dst.split_code(&vd, &d); |
| 2216 emit(cond | 0xE*B24 | index*B21 | vd*B16 | src.code()*B12 | 0xB*B8 | d*B7 | |
| 2217 B4); |
| 2218 } |
| 2219 |
| 2220 |
2136 void Assembler::vmov(const DwVfpRegister dst, | 2221 void Assembler::vmov(const DwVfpRegister dst, |
2137 const Register src1, | 2222 const Register src1, |
2138 const Register src2, | 2223 const Register src2, |
2139 const Condition cond) { | 2224 const Condition cond) { |
2140 // Dm = <Rt,Rt2>. | 2225 // Dm = <Rt,Rt2>. |
2141 // Instruction details available in ARM DDI 0406A, A8-646. | 2226 // Instruction details available in ARM DDI 0406C.b, A8-948. |
2142 // cond(31-28) | 1100(27-24)| 010(23-21) | op=0(20) | Rt2(19-16) | | 2227 // cond(31-28) | 1100(27-24)| 010(23-21) | op=0(20) | Rt2(19-16) | |
2143 // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm | 2228 // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm |
2144 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2229 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2145 ASSERT(!src1.is(pc) && !src2.is(pc)); | 2230 ASSERT(!src1.is(pc) && !src2.is(pc)); |
| 2231 int vm, m; |
| 2232 dst.split_code(&vm, &m); |
2146 emit(cond | 0xC*B24 | B22 | src2.code()*B16 | | 2233 emit(cond | 0xC*B24 | B22 | src2.code()*B16 | |
2147 src1.code()*B12 | 0xB*B8 | B4 | dst.code()); | 2234 src1.code()*B12 | 0xB*B8 | m*B5 | B4 | vm); |
2148 } | 2235 } |
2149 | 2236 |
2150 | 2237 |
2151 void Assembler::vmov(const Register dst1, | 2238 void Assembler::vmov(const Register dst1, |
2152 const Register dst2, | 2239 const Register dst2, |
2153 const DwVfpRegister src, | 2240 const DwVfpRegister src, |
2154 const Condition cond) { | 2241 const Condition cond) { |
2155 // <Rt,Rt2> = Dm. | 2242 // <Rt,Rt2> = Dm. |
2156 // Instruction details available in ARM DDI 0406A, A8-646. | 2243 // Instruction details available in ARM DDI 0406C.b, A8-948. |
2157 // cond(31-28) | 1100(27-24)| 010(23-21) | op=1(20) | Rt2(19-16) | | 2244 // cond(31-28) | 1100(27-24)| 010(23-21) | op=1(20) | Rt2(19-16) | |
2158 // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm | 2245 // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm |
2159 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2246 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2160 ASSERT(!dst1.is(pc) && !dst2.is(pc)); | 2247 ASSERT(!dst1.is(pc) && !dst2.is(pc)); |
| 2248 int vm, m; |
| 2249 src.split_code(&vm, &m); |
2161 emit(cond | 0xC*B24 | B22 | B20 | dst2.code()*B16 | | 2250 emit(cond | 0xC*B24 | B22 | B20 | dst2.code()*B16 | |
2162 dst1.code()*B12 | 0xB*B8 | B4 | src.code()); | 2251 dst1.code()*B12 | 0xB*B8 | m*B5 | B4 | vm); |
2163 } | 2252 } |
2164 | 2253 |
2165 | 2254 |
2166 void Assembler::vmov(const SwVfpRegister dst, | 2255 void Assembler::vmov(const SwVfpRegister dst, |
2167 const Register src, | 2256 const Register src, |
2168 const Condition cond) { | 2257 const Condition cond) { |
2169 // Sn = Rt. | 2258 // Sn = Rt. |
2170 // Instruction details available in ARM DDI 0406A, A8-642. | 2259 // Instruction details available in ARM DDI 0406A, A8-642. |
2171 // cond(31-28) | 1110(27-24)| 000(23-21) | op=0(20) | Vn(19-16) | | 2260 // cond(31-28) | 1110(27-24)| 000(23-21) | op=0(20) | Vn(19-16) | |
2172 // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0) | 2261 // 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... |
2365 VFPConversionMode mode, | 2454 VFPConversionMode mode, |
2366 const Condition cond) { | 2455 const Condition cond) { |
2367 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2456 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2368 emit(EncodeVCVT(F32, dst.code(), F64, src.code(), mode, cond)); | 2457 emit(EncodeVCVT(F32, dst.code(), F64, src.code(), mode, cond)); |
2369 } | 2458 } |
2370 | 2459 |
2371 | 2460 |
2372 void Assembler::vneg(const DwVfpRegister dst, | 2461 void Assembler::vneg(const DwVfpRegister dst, |
2373 const DwVfpRegister src, | 2462 const DwVfpRegister src, |
2374 const Condition cond) { | 2463 const Condition cond) { |
| 2464 // Instruction details available in ARM DDI 0406C.b, A8-968. |
| 2465 // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0001(19-16) | Vd(15-12) | |
| 2466 // 101(11-9) | sz=1(8) | 0(7) | 1(6) | M(5) | 0(4) | Vm(3-0) |
2375 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2467 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2376 emit(cond | 0xE*B24 | 0xB*B20 | B16 | dst.code()*B12 | | 2468 int vd, d; |
2377 0x5*B9 | B8 | B6 | src.code()); | 2469 dst.split_code(&vd, &d); |
| 2470 int vm, m; |
| 2471 src.split_code(&vm, &m); |
| 2472 |
| 2473 emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | B16 | vd*B12 | 0x5*B9 | B8 | B6 | |
| 2474 m*B5 | vm); |
2378 } | 2475 } |
2379 | 2476 |
2380 | 2477 |
2381 void Assembler::vabs(const DwVfpRegister dst, | 2478 void Assembler::vabs(const DwVfpRegister dst, |
2382 const DwVfpRegister src, | 2479 const DwVfpRegister src, |
2383 const Condition cond) { | 2480 const Condition cond) { |
| 2481 // Instruction details available in ARM DDI 0406C.b, A8-524. |
| 2482 // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0000(19-16) | Vd(15-12) | |
| 2483 // 101(11-9) | sz=1(8) | 1(7) | 1(6) | M(5) | 0(4) | Vm(3-0) |
2384 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2484 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2385 emit(cond | 0xE*B24 | 0xB*B20 | dst.code()*B12 | | 2485 int vd, d; |
2386 0x5*B9 | B8 | 0x3*B6 | src.code()); | 2486 dst.split_code(&vd, &d); |
| 2487 int vm, m; |
| 2488 src.split_code(&vm, &m); |
| 2489 emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | vd*B12 | 0x5*B9 | B8 | B7 | B6 | |
| 2490 m*B5 | vm); |
2387 } | 2491 } |
2388 | 2492 |
2389 | 2493 |
2390 void Assembler::vadd(const DwVfpRegister dst, | 2494 void Assembler::vadd(const DwVfpRegister dst, |
2391 const DwVfpRegister src1, | 2495 const DwVfpRegister src1, |
2392 const DwVfpRegister src2, | 2496 const DwVfpRegister src2, |
2393 const Condition cond) { | 2497 const Condition cond) { |
2394 // Dd = vadd(Dn, Dm) double precision floating point addition. | 2498 // Dd = vadd(Dn, Dm) double precision floating point addition. |
2395 // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. | 2499 // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. |
2396 // Instruction details available in ARM DDI 0406A, A8-536. | 2500 // Instruction details available in ARM DDI 0406C.b, A8-830. |
2397 // cond(31-28) | 11100(27-23)| D=?(22) | 11(21-20) | Vn(19-16) | | 2501 // cond(31-28) | 11100(27-23)| D(22) | 11(21-20) | Vn(19-16) | |
2398 // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 0(6) | M=?(5) | 0(4) | Vm(3-0) | 2502 // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0) |
2399 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2503 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2400 emit(cond | 0xE*B24 | 0x3*B20 | src1.code()*B16 | | 2504 int vd, d; |
2401 dst.code()*B12 | 0x5*B9 | B8 | src2.code()); | 2505 dst.split_code(&vd, &d); |
| 2506 int vn, n; |
| 2507 src1.split_code(&vn, &n); |
| 2508 int vm, m; |
| 2509 src2.split_code(&vm, &m); |
| 2510 emit(cond | 0x1C*B23 | d*B22 | 0x3*B20 | vn*B16 | vd*B12 | 0x5*B9 | B8 | |
| 2511 n*B7 | m*B5 | vm); |
2402 } | 2512 } |
2403 | 2513 |
2404 | 2514 |
2405 void Assembler::vsub(const DwVfpRegister dst, | 2515 void Assembler::vsub(const DwVfpRegister dst, |
2406 const DwVfpRegister src1, | 2516 const DwVfpRegister src1, |
2407 const DwVfpRegister src2, | 2517 const DwVfpRegister src2, |
2408 const Condition cond) { | 2518 const Condition cond) { |
2409 // Dd = vsub(Dn, Dm) double precision floating point subtraction. | 2519 // Dd = vsub(Dn, Dm) double precision floating point subtraction. |
2410 // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. | 2520 // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. |
2411 // Instruction details available in ARM DDI 0406A, A8-784. | 2521 // Instruction details available in ARM DDI 0406C.b, A8-1086. |
2412 // cond(31-28) | 11100(27-23)| D=?(22) | 11(21-20) | Vn(19-16) | | 2522 // cond(31-28) | 11100(27-23)| D(22) | 11(21-20) | Vn(19-16) | |
2413 // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 1(6) | M=?(5) | 0(4) | Vm(3-0) | 2523 // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 1(6) | M(5) | 0(4) | Vm(3-0) |
2414 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2524 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2415 emit(cond | 0xE*B24 | 0x3*B20 | src1.code()*B16 | | 2525 int vd, d; |
2416 dst.code()*B12 | 0x5*B9 | B8 | B6 | src2.code()); | 2526 dst.split_code(&vd, &d); |
| 2527 int vn, n; |
| 2528 src1.split_code(&vn, &n); |
| 2529 int vm, m; |
| 2530 src2.split_code(&vm, &m); |
| 2531 emit(cond | 0x1C*B23 | d*B22 | 0x3*B20 | vn*B16 | vd*B12 | 0x5*B9 | B8 | |
| 2532 n*B7 | B6 | m*B5 | vm); |
2417 } | 2533 } |
2418 | 2534 |
2419 | 2535 |
2420 void Assembler::vmul(const DwVfpRegister dst, | 2536 void Assembler::vmul(const DwVfpRegister dst, |
2421 const DwVfpRegister src1, | 2537 const DwVfpRegister src1, |
2422 const DwVfpRegister src2, | 2538 const DwVfpRegister src2, |
2423 const Condition cond) { | 2539 const Condition cond) { |
2424 // Dd = vmul(Dn, Dm) double precision floating point multiplication. | 2540 // Dd = vmul(Dn, Dm) double precision floating point multiplication. |
2425 // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. | 2541 // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. |
2426 // Instruction details available in ARM DDI 0406A, A8-784. | 2542 // Instruction details available in ARM DDI 0406C.b, A8-960. |
2427 // cond(31-28) | 11100(27-23)| D=?(22) | 10(21-20) | Vn(19-16) | | 2543 // cond(31-28) | 11100(27-23)| D(22) | 10(21-20) | Vn(19-16) | |
2428 // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 0(6) | M=?(5) | 0(4) | Vm(3-0) | 2544 // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0) |
2429 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2545 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2430 emit(cond | 0xE*B24 | 0x2*B20 | src1.code()*B16 | | 2546 int vd, d; |
2431 dst.code()*B12 | 0x5*B9 | B8 | src2.code()); | 2547 dst.split_code(&vd, &d); |
| 2548 int vn, n; |
| 2549 src1.split_code(&vn, &n); |
| 2550 int vm, m; |
| 2551 src2.split_code(&vm, &m); |
| 2552 emit(cond | 0x1C*B23 | d*B22 | 0x2*B20 | vn*B16 | vd*B12 | 0x5*B9 | B8 | |
| 2553 n*B7 | m*B5 | vm); |
2432 } | 2554 } |
2433 | 2555 |
2434 | 2556 |
2435 void Assembler::vmla(const DwVfpRegister dst, | 2557 void Assembler::vmla(const DwVfpRegister dst, |
2436 const DwVfpRegister src1, | 2558 const DwVfpRegister src1, |
2437 const DwVfpRegister src2, | 2559 const DwVfpRegister src2, |
2438 const Condition cond) { | 2560 const Condition cond) { |
2439 // Instruction details available in ARM DDI 0406C.b, A8-892. | 2561 // Instruction details available in ARM DDI 0406C.b, A8-932. |
2440 // cond(31-28) | 11100(27-23) | D=?(22) | 00(21-20) | Vn(19-16) | | 2562 // cond(31-28) | 11100(27-23) | D(22) | 00(21-20) | Vn(19-16) | |
2441 // Vd(15-12) | 101(11-9) | sz(8)=1 | N=?(7) | op(6)=0 | M=?(5) | 0(4) | | 2563 // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | op=0(6) | M(5) | 0(4) | Vm(3-0) |
2442 // Vm(3-0) | 2564 int vd, d; |
2443 unsigned x = (cond | 0x1C*B23 | src1.code()*B16 | | 2565 dst.split_code(&vd, &d); |
2444 dst.code()*B12 | 0x5*B9 | B8 | src2.code()); | 2566 int vn, n; |
2445 emit(x); | 2567 src1.split_code(&vn, &n); |
| 2568 int vm, m; |
| 2569 src2.split_code(&vm, &m); |
| 2570 emit(cond | 0x1C*B23 | d*B22 | vn*B16 | vd*B12 | 0x5*B9 | B8 | n*B7 | m*B5 | |
| 2571 vm); |
2446 } | 2572 } |
2447 | 2573 |
2448 | 2574 |
2449 void Assembler::vdiv(const DwVfpRegister dst, | 2575 void Assembler::vdiv(const DwVfpRegister dst, |
2450 const DwVfpRegister src1, | 2576 const DwVfpRegister src1, |
2451 const DwVfpRegister src2, | 2577 const DwVfpRegister src2, |
2452 const Condition cond) { | 2578 const Condition cond) { |
2453 // Dd = vdiv(Dn, Dm) double precision floating point division. | 2579 // Dd = vdiv(Dn, Dm) double precision floating point division. |
2454 // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. | 2580 // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. |
2455 // Instruction details available in ARM DDI 0406A, A8-584. | 2581 // Instruction details available in ARM DDI 0406C.b, A8-882. |
2456 // cond(31-28) | 11101(27-23)| D=?(22) | 00(21-20) | Vn(19-16) | | 2582 // cond(31-28) | 11101(27-23)| D(22) | 00(21-20) | Vn(19-16) | |
2457 // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=? | 0(6) | M=?(5) | 0(4) | Vm(3-0) | 2583 // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0) |
2458 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2584 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2459 emit(cond | 0xE*B24 | B23 | src1.code()*B16 | | 2585 int vd, d; |
2460 dst.code()*B12 | 0x5*B9 | B8 | src2.code()); | 2586 dst.split_code(&vd, &d); |
| 2587 int vn, n; |
| 2588 src1.split_code(&vn, &n); |
| 2589 int vm, m; |
| 2590 src2.split_code(&vm, &m); |
| 2591 emit(cond | 0x1D*B23 | d*B22 | vn*B16 | vd*B12 | 0x5*B9 | B8 | n*B7 | m*B5 | |
| 2592 vm); |
2461 } | 2593 } |
2462 | 2594 |
2463 | 2595 |
2464 void Assembler::vcmp(const DwVfpRegister src1, | 2596 void Assembler::vcmp(const DwVfpRegister src1, |
2465 const DwVfpRegister src2, | 2597 const DwVfpRegister src2, |
2466 const Condition cond) { | 2598 const Condition cond) { |
2467 // vcmp(Dd, Dm) double precision floating point comparison. | 2599 // vcmp(Dd, Dm) double precision floating point comparison. |
2468 // Instruction details available in ARM DDI 0406A, A8-570. | 2600 // Instruction details available in ARM DDI 0406C.b, A8-864. |
2469 // cond(31-28) | 11101 (27-23)| D=?(22) | 11 (21-20) | 0100 (19-16) | | 2601 // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0100(19-16) | |
2470 // Vd(15-12) | 101(11-9) | sz(8)=1 | E(7)=0 | 1(6) | M(5)=? | 0(4) | Vm(3-0) | 2602 // Vd(15-12) | 101(11-9) | sz=1(8) | E=0(7) | 1(6) | M(5) | 0(4) | Vm(3-0) |
2471 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2603 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2472 emit(cond | 0xE*B24 |B23 | 0x3*B20 | B18 | | 2604 int vd, d; |
2473 src1.code()*B12 | 0x5*B9 | B8 | B6 | src2.code()); | 2605 src1.split_code(&vd, &d); |
| 2606 int vm, m; |
| 2607 src2.split_code(&vm, &m); |
| 2608 emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | 0x4*B16 | vd*B12 | 0x5*B9 | B8 | B6 | |
| 2609 m*B5 | vm); |
2474 } | 2610 } |
2475 | 2611 |
2476 | 2612 |
2477 void Assembler::vcmp(const DwVfpRegister src1, | 2613 void Assembler::vcmp(const DwVfpRegister src1, |
2478 const double src2, | 2614 const double src2, |
2479 const Condition cond) { | 2615 const Condition cond) { |
2480 // vcmp(Dd, Dm) double precision floating point comparison. | 2616 // vcmp(Dd, #0.0) double precision floating point comparison. |
2481 // Instruction details available in ARM DDI 0406A, A8-570. | 2617 // Instruction details available in ARM DDI 0406C.b, A8-864. |
2482 // cond(31-28) | 11101 (27-23)| D=?(22) | 11 (21-20) | 0101 (19-16) | | 2618 // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0101(19-16) | |
2483 // Vd(15-12) | 101(11-9) | sz(8)=1 | E(7)=0 | 1(6) | M(5)=? | 0(4) | 0000(3-0) | 2619 // Vd(15-12) | 101(11-9) | sz=1(8) | E=0(7) | 1(6) | 0(5) | 0(4) | 0000(3-0) |
2484 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2620 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2485 ASSERT(src2 == 0.0); | 2621 ASSERT(src2 == 0.0); |
2486 emit(cond | 0xE*B24 |B23 | 0x3*B20 | B18 | B16 | | 2622 int vd, d; |
2487 src1.code()*B12 | 0x5*B9 | B8 | B6); | 2623 src1.split_code(&vd, &d); |
| 2624 emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | 0x5*B16 | vd*B12 | 0x5*B9 | B8 | B6); |
2488 } | 2625 } |
2489 | 2626 |
2490 | 2627 |
2491 void Assembler::vmsr(Register dst, Condition cond) { | 2628 void Assembler::vmsr(Register dst, Condition cond) { |
2492 // Instruction details available in ARM DDI 0406A, A8-652. | 2629 // Instruction details available in ARM DDI 0406A, A8-652. |
2493 // cond(31-28) | 1110 (27-24) | 1110(23-20)| 0001 (19-16) | | 2630 // cond(31-28) | 1110 (27-24) | 1110(23-20)| 0001 (19-16) | |
2494 // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0) | 2631 // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0) |
2495 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2632 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2496 emit(cond | 0xE*B24 | 0xE*B20 | B16 | | 2633 emit(cond | 0xE*B24 | 0xE*B20 | B16 | |
2497 dst.code()*B12 | 0xA*B8 | B4); | 2634 dst.code()*B12 | 0xA*B8 | B4); |
2498 } | 2635 } |
2499 | 2636 |
2500 | 2637 |
2501 void Assembler::vmrs(Register dst, Condition cond) { | 2638 void Assembler::vmrs(Register dst, Condition cond) { |
2502 // Instruction details available in ARM DDI 0406A, A8-652. | 2639 // Instruction details available in ARM DDI 0406A, A8-652. |
2503 // cond(31-28) | 1110 (27-24) | 1111(23-20)| 0001 (19-16) | | 2640 // cond(31-28) | 1110 (27-24) | 1111(23-20)| 0001 (19-16) | |
2504 // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0) | 2641 // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0) |
2505 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2642 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2506 emit(cond | 0xE*B24 | 0xF*B20 | B16 | | 2643 emit(cond | 0xE*B24 | 0xF*B20 | B16 | |
2507 dst.code()*B12 | 0xA*B8 | B4); | 2644 dst.code()*B12 | 0xA*B8 | B4); |
2508 } | 2645 } |
2509 | 2646 |
2510 | 2647 |
2511 void Assembler::vsqrt(const DwVfpRegister dst, | 2648 void Assembler::vsqrt(const DwVfpRegister dst, |
2512 const DwVfpRegister src, | 2649 const DwVfpRegister src, |
2513 const Condition cond) { | 2650 const Condition cond) { |
2514 // cond(31-28) | 11101 (27-23)| D=?(22) | 11 (21-20) | 0001 (19-16) | | 2651 // Instruction details available in ARM DDI 0406C.b, A8-1058. |
2515 // Vd(15-12) | 101(11-9) | sz(8)=1 | 11 (7-6) | M(5)=? | 0(4) | Vm(3-0) | 2652 // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0001(19-16) | |
| 2653 // Vd(15-12) | 101(11-9) | sz=1(8) | 11(7-6) | M(5) | 0(4) | Vm(3-0) |
2516 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2654 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2517 emit(cond | 0xE*B24 | B23 | 0x3*B20 | B16 | | 2655 int vd, d; |
2518 dst.code()*B12 | 0x5*B9 | B8 | 3*B6 | src.code()); | 2656 dst.split_code(&vd, &d); |
| 2657 int vm, m; |
| 2658 src.split_code(&vm, &m); |
| 2659 emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | B16 | vd*B12 | 0x5*B9 | B8 | 0x3*B6 | |
| 2660 m*B5 | vm); |
2519 } | 2661 } |
2520 | 2662 |
2521 | 2663 |
2522 // Pseudo instructions. | 2664 // Pseudo instructions. |
2523 void Assembler::nop(int type) { | 2665 void Assembler::nop(int type) { |
2524 // ARMv6{K/T2} and v7 have an actual NOP instruction but it serializes | 2666 // ARMv6{K/T2} and v7 have an actual NOP instruction but it serializes |
2525 // some of the CPU's pipeline and has to issue. Older ARM chips simply used | 2667 // some of the CPU's pipeline and has to issue. Older ARM chips simply used |
2526 // MOV Rx, Rx as NOP and it performs better even in newer CPUs. | 2668 // MOV Rx, Rx as NOP and it performs better even in newer CPUs. |
2527 // We therefore use MOV Rx, Rx, even on newer CPUs, and use Rx to encode | 2669 // We therefore use MOV Rx, Rx, even on newer CPUs, and use Rx to encode |
2528 // a type. | 2670 // a type. |
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2919 | 3061 |
2920 // Since a constant pool was just emitted, move the check offset forward by | 3062 // Since a constant pool was just emitted, move the check offset forward by |
2921 // the standard interval. | 3063 // the standard interval. |
2922 next_buffer_check_ = pc_offset() + kCheckPoolInterval; | 3064 next_buffer_check_ = pc_offset() + kCheckPoolInterval; |
2923 } | 3065 } |
2924 | 3066 |
2925 | 3067 |
2926 } } // namespace v8::internal | 3068 } } // namespace v8::internal |
2927 | 3069 |
2928 #endif // V8_TARGET_ARCH_ARM | 3070 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |