Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(381)

Side by Side Diff: src/arm/assembler-arm.cc

Issue 11428137: ARM: Make use of d16-d31 when available. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Rebase Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/arm/assembler-arm.h ('k') | src/arm/assembler-arm-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/arm/assembler-arm.h ('k') | src/arm/assembler-arm-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698