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)); | 2142 mov(ip, Operand(lo)); |
2092 | 2143 |
2093 if (scratch.is(no_reg)) { | 2144 if (scratch.is(no_reg)) { |
2094 // Move the low part of the double into the lower of the corresponsing S | 2145 // Move the low and high part separately using vmov.32. |
2095 // registers of D register dst. | 2146 vmov(dst, 0, ip, cond); |
2096 vmov(dst.low(), ip, cond); | |
2097 | |
2098 // Move the high part of the double into the higher of the corresponsing S | |
2099 // registers of D register dst. | |
2100 mov(ip, Operand(hi)); | 2147 mov(ip, Operand(hi)); |
2101 vmov(dst.high(), ip, cond); | 2148 vmov(dst, 1, ip, cond); |
2102 } else { | 2149 } else { |
2103 // Move the low and high parts of the double to a D register in one | 2150 // Move the low and high parts of the double to a D register in one |
2104 // instruction. | 2151 // instruction. |
2105 mov(scratch, Operand(hi)); | 2152 mov(scratch, Operand(hi)); |
2106 vmov(dst, ip, scratch, cond); | 2153 vmov(dst, ip, scratch, cond); |
2107 } | 2154 } |
2108 } | 2155 } |
2109 } | 2156 } |
2110 | 2157 |
2111 | 2158 |
2112 void Assembler::vmov(const SwVfpRegister dst, | 2159 void Assembler::vmov(const SwVfpRegister dst, |
2113 const SwVfpRegister src, | 2160 const SwVfpRegister src, |
2114 const Condition cond) { | 2161 const Condition cond) { |
2115 // Sd = Sm | 2162 // Sd = Sm |
2116 // Instruction details available in ARM DDI 0406B, A8-642. | 2163 // Instruction details available in ARM DDI 0406B, A8-642. |
2117 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2164 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2118 int sd, d, sm, m; | 2165 int sd, d, sm, m; |
2119 dst.split_code(&sd, &d); | 2166 dst.split_code(&sd, &d); |
2120 src.split_code(&sm, &m); | 2167 src.split_code(&sm, &m); |
2121 emit(cond | 0xE*B24 | d*B22 | 0xB*B20 | sd*B12 | 0xA*B8 | B6 | m*B5 | sm); | 2168 emit(cond | 0xE*B24 | d*B22 | 0xB*B20 | sd*B12 | 0xA*B8 | B6 | m*B5 | sm); |
2122 } | 2169 } |
2123 | 2170 |
2124 | 2171 |
2125 void Assembler::vmov(const DwVfpRegister dst, | 2172 void Assembler::vmov(const DwVfpRegister dst, |
2126 const DwVfpRegister src, | 2173 const DwVfpRegister src, |
2127 const Condition cond) { | 2174 const Condition cond) { |
2128 // Dd = Dm | 2175 // Dd = Dm |
2129 // Instruction details available in ARM DDI 0406B, A8-642. | 2176 // Instruction details available in ARM DDI 0406C.b, A8-938. |
| 2177 // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0000(19-16) | Vd(15-12) | |
| 2178 // 101(11-9) | sz=1(8) | 0(7) | 1(6) | M(5) | 0(4) | Vm(3-0) |
2130 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2179 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2131 emit(cond | 0xE*B24 | 0xB*B20 | | 2180 int vd, d; |
2132 dst.code()*B12 | 0x5*B9 | B8 | B6 | src.code()); | 2181 dst.split_code(&vd, &d); |
| 2182 int vm, m; |
| 2183 src.split_code(&vm, &m); |
| 2184 emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | vd*B12 | 0x5*B9 | B8 | B6 | m*B5 | |
| 2185 vm); |
2133 } | 2186 } |
2134 | 2187 |
2135 | 2188 |
| 2189 void Assembler::vmov(const DwVfpRegister dst, |
| 2190 int index, |
| 2191 const Register src, |
| 2192 const Condition cond) { |
| 2193 // Dd[index] = Rt |
| 2194 // Instruction details available in ARM DDI 0406C.b, A8-940. |
| 2195 // cond(31-28) | 1110(27-24) | 0(23) | opc1=0index(22-21) | 0(20) | |
| 2196 // Vd(19-16) | Rt(15-12) | 1011(11-8) | D(7) | opc2=00(6-5) | 1(4) | 0000(3-0) |
| 2197 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
| 2198 ASSERT(index == 0 || index == 1); |
| 2199 int vd, d; |
| 2200 dst.split_code(&vd, &d); |
| 2201 emit(cond | 0xE*B24 | index*B21 | vd*B16 | src.code()*B12 | 0xB*B8 | d*B7 | |
| 2202 B4); |
| 2203 } |
| 2204 |
| 2205 |
2136 void Assembler::vmov(const DwVfpRegister dst, | 2206 void Assembler::vmov(const DwVfpRegister dst, |
2137 const Register src1, | 2207 const Register src1, |
2138 const Register src2, | 2208 const Register src2, |
2139 const Condition cond) { | 2209 const Condition cond) { |
2140 // Dm = <Rt,Rt2>. | 2210 // Dm = <Rt,Rt2>. |
2141 // Instruction details available in ARM DDI 0406A, A8-646. | 2211 // 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) | | 2212 // 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 | 2213 // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm |
2144 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2214 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2145 ASSERT(!src1.is(pc) && !src2.is(pc)); | 2215 ASSERT(!src1.is(pc) && !src2.is(pc)); |
| 2216 int vm, m; |
| 2217 dst.split_code(&vm, &m); |
2146 emit(cond | 0xC*B24 | B22 | src2.code()*B16 | | 2218 emit(cond | 0xC*B24 | B22 | src2.code()*B16 | |
2147 src1.code()*B12 | 0xB*B8 | B4 | dst.code()); | 2219 src1.code()*B12 | 0xB*B8 | m*B5 | B4 | vm); |
2148 } | 2220 } |
2149 | 2221 |
2150 | 2222 |
2151 void Assembler::vmov(const Register dst1, | 2223 void Assembler::vmov(const Register dst1, |
2152 const Register dst2, | 2224 const Register dst2, |
2153 const DwVfpRegister src, | 2225 const DwVfpRegister src, |
2154 const Condition cond) { | 2226 const Condition cond) { |
2155 // <Rt,Rt2> = Dm. | 2227 // <Rt,Rt2> = Dm. |
2156 // Instruction details available in ARM DDI 0406A, A8-646. | 2228 // 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) | | 2229 // 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 | 2230 // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm |
2159 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2231 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2160 ASSERT(!dst1.is(pc) && !dst2.is(pc)); | 2232 ASSERT(!dst1.is(pc) && !dst2.is(pc)); |
| 2233 int vm, m; |
| 2234 src.split_code(&vm, &m); |
2161 emit(cond | 0xC*B24 | B22 | B20 | dst2.code()*B16 | | 2235 emit(cond | 0xC*B24 | B22 | B20 | dst2.code()*B16 | |
2162 dst1.code()*B12 | 0xB*B8 | B4 | src.code()); | 2236 dst1.code()*B12 | 0xB*B8 | m*B5 | B4 | vm); |
2163 } | 2237 } |
2164 | 2238 |
2165 | 2239 |
2166 void Assembler::vmov(const SwVfpRegister dst, | 2240 void Assembler::vmov(const SwVfpRegister dst, |
2167 const Register src, | 2241 const Register src, |
2168 const Condition cond) { | 2242 const Condition cond) { |
2169 // Sn = Rt. | 2243 // Sn = Rt. |
2170 // Instruction details available in ARM DDI 0406A, A8-642. | 2244 // 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) | | 2245 // 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) | 2246 // 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, | 2439 VFPConversionMode mode, |
2366 const Condition cond) { | 2440 const Condition cond) { |
2367 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2441 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2368 emit(EncodeVCVT(F32, dst.code(), F64, src.code(), mode, cond)); | 2442 emit(EncodeVCVT(F32, dst.code(), F64, src.code(), mode, cond)); |
2369 } | 2443 } |
2370 | 2444 |
2371 | 2445 |
2372 void Assembler::vneg(const DwVfpRegister dst, | 2446 void Assembler::vneg(const DwVfpRegister dst, |
2373 const DwVfpRegister src, | 2447 const DwVfpRegister src, |
2374 const Condition cond) { | 2448 const Condition cond) { |
| 2449 // Instruction details available in ARM DDI 0406C.b, A8-968. |
| 2450 // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0001(19-16) | Vd(15-12) | |
| 2451 // 101(11-9) | sz=1(8) | 0(7) | 1(6) | M(5) | 0(4) | Vm(3-0) |
2375 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2452 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2376 emit(cond | 0xE*B24 | 0xB*B20 | B16 | dst.code()*B12 | | 2453 int vd, d; |
2377 0x5*B9 | B8 | B6 | src.code()); | 2454 dst.split_code(&vd, &d); |
| 2455 int vm, m; |
| 2456 src.split_code(&vm, &m); |
| 2457 |
| 2458 emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | B16 | vd*B12 | 0x5*B9 | B8 | B6 | |
| 2459 m*B5 | vm); |
2378 } | 2460 } |
2379 | 2461 |
2380 | 2462 |
2381 void Assembler::vabs(const DwVfpRegister dst, | 2463 void Assembler::vabs(const DwVfpRegister dst, |
2382 const DwVfpRegister src, | 2464 const DwVfpRegister src, |
2383 const Condition cond) { | 2465 const Condition cond) { |
| 2466 // Instruction details available in ARM DDI 0406C.b, A8-524. |
| 2467 // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0000(19-16) | Vd(15-12) | |
| 2468 // 101(11-9) | sz=1(8) | 1(7) | 1(6) | M(5) | 0(4) | Vm(3-0) |
2384 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2469 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2385 emit(cond | 0xE*B24 | 0xB*B20 | dst.code()*B12 | | 2470 int vd, d; |
2386 0x5*B9 | B8 | 0x3*B6 | src.code()); | 2471 dst.split_code(&vd, &d); |
| 2472 int vm, m; |
| 2473 src.split_code(&vm, &m); |
| 2474 emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | vd*B12 | 0x5*B9 | B8 | B7 | B6 | |
| 2475 m*B5 | vm); |
2387 } | 2476 } |
2388 | 2477 |
2389 | 2478 |
2390 void Assembler::vadd(const DwVfpRegister dst, | 2479 void Assembler::vadd(const DwVfpRegister dst, |
2391 const DwVfpRegister src1, | 2480 const DwVfpRegister src1, |
2392 const DwVfpRegister src2, | 2481 const DwVfpRegister src2, |
2393 const Condition cond) { | 2482 const Condition cond) { |
2394 // Dd = vadd(Dn, Dm) double precision floating point addition. | 2483 // Dd = vadd(Dn, Dm) double precision floating point addition. |
2395 // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. | 2484 // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. |
2396 // Instruction details available in ARM DDI 0406A, A8-536. | 2485 // 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) | | 2486 // 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) | 2487 // 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)); | 2488 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2400 emit(cond | 0xE*B24 | 0x3*B20 | src1.code()*B16 | | 2489 int vd, d; |
2401 dst.code()*B12 | 0x5*B9 | B8 | src2.code()); | 2490 dst.split_code(&vd, &d); |
| 2491 int vn, n; |
| 2492 src1.split_code(&vn, &n); |
| 2493 int vm, m; |
| 2494 src2.split_code(&vm, &m); |
| 2495 emit(cond | 0x1C*B23 | d*B22 | 0x3*B20 | vn*B16 | vd*B12 | 0x5*B9 | B8 | |
| 2496 n*B7 | m*B5 | vm); |
2402 } | 2497 } |
2403 | 2498 |
2404 | 2499 |
2405 void Assembler::vsub(const DwVfpRegister dst, | 2500 void Assembler::vsub(const DwVfpRegister dst, |
2406 const DwVfpRegister src1, | 2501 const DwVfpRegister src1, |
2407 const DwVfpRegister src2, | 2502 const DwVfpRegister src2, |
2408 const Condition cond) { | 2503 const Condition cond) { |
2409 // Dd = vsub(Dn, Dm) double precision floating point subtraction. | 2504 // Dd = vsub(Dn, Dm) double precision floating point subtraction. |
2410 // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. | 2505 // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. |
2411 // Instruction details available in ARM DDI 0406A, A8-784. | 2506 // 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) | | 2507 // 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) | 2508 // 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)); | 2509 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2415 emit(cond | 0xE*B24 | 0x3*B20 | src1.code()*B16 | | 2510 int vd, d; |
2416 dst.code()*B12 | 0x5*B9 | B8 | B6 | src2.code()); | 2511 dst.split_code(&vd, &d); |
| 2512 int vn, n; |
| 2513 src1.split_code(&vn, &n); |
| 2514 int vm, m; |
| 2515 src2.split_code(&vm, &m); |
| 2516 emit(cond | 0x1C*B23 | d*B22 | 0x3*B20 | vn*B16 | vd*B12 | 0x5*B9 | B8 | |
| 2517 n*B7 | B6 | m*B5 | vm); |
2417 } | 2518 } |
2418 | 2519 |
2419 | 2520 |
2420 void Assembler::vmul(const DwVfpRegister dst, | 2521 void Assembler::vmul(const DwVfpRegister dst, |
2421 const DwVfpRegister src1, | 2522 const DwVfpRegister src1, |
2422 const DwVfpRegister src2, | 2523 const DwVfpRegister src2, |
2423 const Condition cond) { | 2524 const Condition cond) { |
2424 // Dd = vmul(Dn, Dm) double precision floating point multiplication. | 2525 // Dd = vmul(Dn, Dm) double precision floating point multiplication. |
2425 // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. | 2526 // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. |
2426 // Instruction details available in ARM DDI 0406A, A8-784. | 2527 // 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) | | 2528 // 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) | 2529 // 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)); | 2530 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2430 emit(cond | 0xE*B24 | 0x2*B20 | src1.code()*B16 | | 2531 int vd, d; |
2431 dst.code()*B12 | 0x5*B9 | B8 | src2.code()); | 2532 dst.split_code(&vd, &d); |
| 2533 int vn, n; |
| 2534 src1.split_code(&vn, &n); |
| 2535 int vm, m; |
| 2536 src2.split_code(&vm, &m); |
| 2537 emit(cond | 0x1C*B23 | d*B22 | 0x2*B20 | vn*B16 | vd*B12 | 0x5*B9 | B8 | |
| 2538 n*B7 | m*B5 | vm); |
2432 } | 2539 } |
2433 | 2540 |
2434 | 2541 |
2435 void Assembler::vmla(const DwVfpRegister dst, | 2542 void Assembler::vmla(const DwVfpRegister dst, |
2436 const DwVfpRegister src1, | 2543 const DwVfpRegister src1, |
2437 const DwVfpRegister src2, | 2544 const DwVfpRegister src2, |
2438 const Condition cond) { | 2545 const Condition cond) { |
2439 // Instruction details available in ARM DDI 0406C.b, A8-892. | 2546 // 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) | | 2547 // 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) | | 2548 // 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) | 2549 int vd, d; |
2443 unsigned x = (cond | 0x1C*B23 | src1.code()*B16 | | 2550 dst.split_code(&vd, &d); |
2444 dst.code()*B12 | 0x5*B9 | B8 | src2.code()); | 2551 int vn, n; |
2445 emit(x); | 2552 src1.split_code(&vn, &n); |
| 2553 int vm, m; |
| 2554 src2.split_code(&vm, &m); |
| 2555 emit(cond | 0x1C*B23 | d*B22 | vn*B16 | vd*B12 | 0x5*B9 | B8 | n*B7 | m*B5 | |
| 2556 vm); |
2446 } | 2557 } |
2447 | 2558 |
2448 | 2559 |
2449 void Assembler::vdiv(const DwVfpRegister dst, | 2560 void Assembler::vdiv(const DwVfpRegister dst, |
2450 const DwVfpRegister src1, | 2561 const DwVfpRegister src1, |
2451 const DwVfpRegister src2, | 2562 const DwVfpRegister src2, |
2452 const Condition cond) { | 2563 const Condition cond) { |
2453 // Dd = vdiv(Dn, Dm) double precision floating point division. | 2564 // Dd = vdiv(Dn, Dm) double precision floating point division. |
2454 // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. | 2565 // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. |
2455 // Instruction details available in ARM DDI 0406A, A8-584. | 2566 // 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) | | 2567 // 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) | 2568 // 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)); | 2569 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2459 emit(cond | 0xE*B24 | B23 | src1.code()*B16 | | 2570 int vd, d; |
2460 dst.code()*B12 | 0x5*B9 | B8 | src2.code()); | 2571 dst.split_code(&vd, &d); |
| 2572 int vn, n; |
| 2573 src1.split_code(&vn, &n); |
| 2574 int vm, m; |
| 2575 src2.split_code(&vm, &m); |
| 2576 emit(cond | 0x1D*B23 | d*B22 | vn*B16 | vd*B12 | 0x5*B9 | B8 | n*B7 | m*B5 | |
| 2577 vm); |
2461 } | 2578 } |
2462 | 2579 |
2463 | 2580 |
2464 void Assembler::vcmp(const DwVfpRegister src1, | 2581 void Assembler::vcmp(const DwVfpRegister src1, |
2465 const DwVfpRegister src2, | 2582 const DwVfpRegister src2, |
2466 const Condition cond) { | 2583 const Condition cond) { |
2467 // vcmp(Dd, Dm) double precision floating point comparison. | 2584 // vcmp(Dd, Dm) double precision floating point comparison. |
2468 // Instruction details available in ARM DDI 0406A, A8-570. | 2585 // 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) | | 2586 // 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) | 2587 // 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)); | 2588 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2472 emit(cond | 0xE*B24 |B23 | 0x3*B20 | B18 | | 2589 int vd, d; |
2473 src1.code()*B12 | 0x5*B9 | B8 | B6 | src2.code()); | 2590 src1.split_code(&vd, &d); |
| 2591 int vm, m; |
| 2592 src2.split_code(&vm, &m); |
| 2593 emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | 0x4*B16 | vd*B12 | 0x5*B9 | B8 | B6 | |
| 2594 m*B5 | vm); |
2474 } | 2595 } |
2475 | 2596 |
2476 | 2597 |
2477 void Assembler::vcmp(const DwVfpRegister src1, | 2598 void Assembler::vcmp(const DwVfpRegister src1, |
2478 const double src2, | 2599 const double src2, |
2479 const Condition cond) { | 2600 const Condition cond) { |
2480 // vcmp(Dd, Dm) double precision floating point comparison. | 2601 // vcmp(Dd, #0.0) double precision floating point comparison. |
2481 // Instruction details available in ARM DDI 0406A, A8-570. | 2602 // 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) | | 2603 // 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) | 2604 // 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)); | 2605 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2485 ASSERT(src2 == 0.0); | 2606 ASSERT(src2 == 0.0); |
2486 emit(cond | 0xE*B24 |B23 | 0x3*B20 | B18 | B16 | | 2607 int vd, d; |
2487 src1.code()*B12 | 0x5*B9 | B8 | B6); | 2608 src1.split_code(&vd, &d); |
| 2609 emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | 0x5*B16 | vd*B12 | 0x5*B9 | B8 | B6); |
2488 } | 2610 } |
2489 | 2611 |
2490 | 2612 |
2491 void Assembler::vmsr(Register dst, Condition cond) { | 2613 void Assembler::vmsr(Register dst, Condition cond) { |
2492 // Instruction details available in ARM DDI 0406A, A8-652. | 2614 // Instruction details available in ARM DDI 0406A, A8-652. |
2493 // cond(31-28) | 1110 (27-24) | 1110(23-20)| 0001 (19-16) | | 2615 // 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) | 2616 // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0) |
2495 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2617 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2496 emit(cond | 0xE*B24 | 0xE*B20 | B16 | | 2618 emit(cond | 0xE*B24 | 0xE*B20 | B16 | |
2497 dst.code()*B12 | 0xA*B8 | B4); | 2619 dst.code()*B12 | 0xA*B8 | B4); |
2498 } | 2620 } |
2499 | 2621 |
2500 | 2622 |
2501 void Assembler::vmrs(Register dst, Condition cond) { | 2623 void Assembler::vmrs(Register dst, Condition cond) { |
2502 // Instruction details available in ARM DDI 0406A, A8-652. | 2624 // Instruction details available in ARM DDI 0406A, A8-652. |
2503 // cond(31-28) | 1110 (27-24) | 1111(23-20)| 0001 (19-16) | | 2625 // 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) | 2626 // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0) |
2505 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2627 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2506 emit(cond | 0xE*B24 | 0xF*B20 | B16 | | 2628 emit(cond | 0xE*B24 | 0xF*B20 | B16 | |
2507 dst.code()*B12 | 0xA*B8 | B4); | 2629 dst.code()*B12 | 0xA*B8 | B4); |
2508 } | 2630 } |
2509 | 2631 |
2510 | 2632 |
2511 void Assembler::vsqrt(const DwVfpRegister dst, | 2633 void Assembler::vsqrt(const DwVfpRegister dst, |
2512 const DwVfpRegister src, | 2634 const DwVfpRegister src, |
2513 const Condition cond) { | 2635 const Condition cond) { |
2514 // cond(31-28) | 11101 (27-23)| D=?(22) | 11 (21-20) | 0001 (19-16) | | 2636 // 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) | 2637 // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0001(19-16) | |
| 2638 // Vd(15-12) | 101(11-9) | sz=1(8) | 11(7-6) | M(5) | 0(4) | Vm(3-0) |
2516 ASSERT(CpuFeatures::IsEnabled(VFP2)); | 2639 ASSERT(CpuFeatures::IsEnabled(VFP2)); |
2517 emit(cond | 0xE*B24 | B23 | 0x3*B20 | B16 | | 2640 int vd, d; |
2518 dst.code()*B12 | 0x5*B9 | B8 | 3*B6 | src.code()); | 2641 dst.split_code(&vd, &d); |
| 2642 int vm, m; |
| 2643 src.split_code(&vm, &m); |
| 2644 emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | B16 | vd*B12 | 0x5*B9 | B8 | 0x3*B6 | |
| 2645 m*B5 | vm); |
2519 } | 2646 } |
2520 | 2647 |
2521 | 2648 |
2522 // Pseudo instructions. | 2649 // Pseudo instructions. |
2523 void Assembler::nop(int type) { | 2650 void Assembler::nop(int type) { |
2524 // ARMv6{K/T2} and v7 have an actual NOP instruction but it serializes | 2651 // 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 | 2652 // 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. | 2653 // 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 | 2654 // We therefore use MOV Rx, Rx, even on newer CPUs, and use Rx to encode |
2528 // a type. | 2655 // a type. |
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2919 | 3046 |
2920 // Since a constant pool was just emitted, move the check offset forward by | 3047 // Since a constant pool was just emitted, move the check offset forward by |
2921 // the standard interval. | 3048 // the standard interval. |
2922 next_buffer_check_ = pc_offset() + kCheckPoolInterval; | 3049 next_buffer_check_ = pc_offset() + kCheckPoolInterval; |
2923 } | 3050 } |
2924 | 3051 |
2925 | 3052 |
2926 } } // namespace v8::internal | 3053 } } // namespace v8::internal |
2927 | 3054 |
2928 #endif // V8_TARGET_ARCH_ARM | 3055 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |