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

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

Issue 2896303003: Reland of Reland of "ARM64: Add NEON support" (Closed)
Patch Set: Created 3 years, 7 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
« no previous file with comments | « src/arm64/assembler-arm64.h ('k') | src/arm64/assembler-arm64-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 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // 2 //
3 // Redistribution and use in source and binary forms, with or without 3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are 4 // modification, are permitted provided that the following conditions are
5 // met: 5 // met:
6 // 6 //
7 // * Redistributions of source code must retain the above copyright 7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer. 8 // notice, this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above 9 // * Redistributions in binary form must reproduce the above
10 // copyright notice, this list of conditions and the following 10 // copyright notice, this list of conditions and the following
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
82 index = kRegListSizeInBits - 1 - index; 82 index = kRegListSizeInBits - 1 - index;
83 DCHECK((1 << index) & list_); 83 DCHECK((1 << index) & list_);
84 Remove(index); 84 Remove(index);
85 return CPURegister::Create(index, size_, type_); 85 return CPURegister::Create(index, size_, type_);
86 } 86 }
87 87
88 88
89 void CPURegList::RemoveCalleeSaved() { 89 void CPURegList::RemoveCalleeSaved() {
90 if (type() == CPURegister::kRegister) { 90 if (type() == CPURegister::kRegister) {
91 Remove(GetCalleeSaved(RegisterSizeInBits())); 91 Remove(GetCalleeSaved(RegisterSizeInBits()));
92 } else if (type() == CPURegister::kFPRegister) { 92 } else if (type() == CPURegister::kVRegister) {
93 Remove(GetCalleeSavedFP(RegisterSizeInBits())); 93 Remove(GetCalleeSavedV(RegisterSizeInBits()));
94 } else { 94 } else {
95 DCHECK(type() == CPURegister::kNoRegister); 95 DCHECK(type() == CPURegister::kNoRegister);
96 DCHECK(IsEmpty()); 96 DCHECK(IsEmpty());
97 // The list must already be empty, so do nothing. 97 // The list must already be empty, so do nothing.
98 } 98 }
99 } 99 }
100 100
101 101
102 CPURegList CPURegList::GetCalleeSaved(int size) { 102 CPURegList CPURegList::GetCalleeSaved(int size) {
103 return CPURegList(CPURegister::kRegister, size, 19, 29); 103 return CPURegList(CPURegister::kRegister, size, 19, 29);
104 } 104 }
105 105
106 106 CPURegList CPURegList::GetCalleeSavedV(int size) {
107 CPURegList CPURegList::GetCalleeSavedFP(int size) { 107 return CPURegList(CPURegister::kVRegister, size, 8, 15);
108 return CPURegList(CPURegister::kFPRegister, size, 8, 15);
109 } 108 }
110 109
111 110
112 CPURegList CPURegList::GetCallerSaved(int size) { 111 CPURegList CPURegList::GetCallerSaved(int size) {
113 // Registers x0-x18 and lr (x30) are caller-saved. 112 // Registers x0-x18 and lr (x30) are caller-saved.
114 CPURegList list = CPURegList(CPURegister::kRegister, size, 0, 18); 113 CPURegList list = CPURegList(CPURegister::kRegister, size, 0, 18);
115 list.Combine(lr); 114 list.Combine(lr);
116 return list; 115 return list;
117 } 116 }
118 117
119 118 CPURegList CPURegList::GetCallerSavedV(int size) {
120 CPURegList CPURegList::GetCallerSavedFP(int size) {
121 // Registers d0-d7 and d16-d31 are caller-saved. 119 // Registers d0-d7 and d16-d31 are caller-saved.
122 CPURegList list = CPURegList(CPURegister::kFPRegister, size, 0, 7); 120 CPURegList list = CPURegList(CPURegister::kVRegister, size, 0, 7);
123 list.Combine(CPURegList(CPURegister::kFPRegister, size, 16, 31)); 121 list.Combine(CPURegList(CPURegister::kVRegister, size, 16, 31));
124 return list; 122 return list;
125 } 123 }
126 124
127 125
128 // This function defines the list of registers which are associated with a 126 // This function defines the list of registers which are associated with a
129 // safepoint slot. Safepoint register slots are saved contiguously on the stack. 127 // safepoint slot. Safepoint register slots are saved contiguously on the stack.
130 // MacroAssembler::SafepointRegisterStackIndex handles mapping from register 128 // MacroAssembler::SafepointRegisterStackIndex handles mapping from register
131 // code to index in the safepoint register slots. Any change here can affect 129 // code to index in the safepoint register slots. Any change here can affect
132 // this mapping. 130 // this mapping.
133 CPURegList CPURegList::GetSafepointSavedRegisters() { 131 CPURegList CPURegList::GetSafepointSavedRegisters() {
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
232 230
233 RegList unique_regs = 0; 231 RegList unique_regs = 0;
234 RegList unique_fpregs = 0; 232 RegList unique_fpregs = 0;
235 233
236 const CPURegister regs[] = {reg1, reg2, reg3, reg4, reg5, reg6, reg7, reg8}; 234 const CPURegister regs[] = {reg1, reg2, reg3, reg4, reg5, reg6, reg7, reg8};
237 235
238 for (unsigned i = 0; i < arraysize(regs); i++) { 236 for (unsigned i = 0; i < arraysize(regs); i++) {
239 if (regs[i].IsRegister()) { 237 if (regs[i].IsRegister()) {
240 number_of_valid_regs++; 238 number_of_valid_regs++;
241 unique_regs |= regs[i].Bit(); 239 unique_regs |= regs[i].Bit();
242 } else if (regs[i].IsFPRegister()) { 240 } else if (regs[i].IsVRegister()) {
243 number_of_valid_fpregs++; 241 number_of_valid_fpregs++;
244 unique_fpregs |= regs[i].Bit(); 242 unique_fpregs |= regs[i].Bit();
245 } else { 243 } else {
246 DCHECK(!regs[i].IsValid()); 244 DCHECK(!regs[i].IsValid());
247 } 245 }
248 } 246 }
249 247
250 int number_of_unique_regs = 248 int number_of_unique_regs =
251 CountSetBits(unique_regs, sizeof(unique_regs) * kBitsPerByte); 249 CountSetBits(unique_regs, sizeof(unique_regs) * kBitsPerByte);
252 int number_of_unique_fpregs = 250 int number_of_unique_fpregs =
(...skipping 16 matching lines...) Expand all
269 match &= !reg2.IsValid() || reg2.IsSameSizeAndType(reg1); 267 match &= !reg2.IsValid() || reg2.IsSameSizeAndType(reg1);
270 match &= !reg3.IsValid() || reg3.IsSameSizeAndType(reg1); 268 match &= !reg3.IsValid() || reg3.IsSameSizeAndType(reg1);
271 match &= !reg4.IsValid() || reg4.IsSameSizeAndType(reg1); 269 match &= !reg4.IsValid() || reg4.IsSameSizeAndType(reg1);
272 match &= !reg5.IsValid() || reg5.IsSameSizeAndType(reg1); 270 match &= !reg5.IsValid() || reg5.IsSameSizeAndType(reg1);
273 match &= !reg6.IsValid() || reg6.IsSameSizeAndType(reg1); 271 match &= !reg6.IsValid() || reg6.IsSameSizeAndType(reg1);
274 match &= !reg7.IsValid() || reg7.IsSameSizeAndType(reg1); 272 match &= !reg7.IsValid() || reg7.IsSameSizeAndType(reg1);
275 match &= !reg8.IsValid() || reg8.IsSameSizeAndType(reg1); 273 match &= !reg8.IsValid() || reg8.IsSameSizeAndType(reg1);
276 return match; 274 return match;
277 } 275 }
278 276
277 bool AreSameFormat(const VRegister& reg1, const VRegister& reg2,
278 const VRegister& reg3, const VRegister& reg4) {
279 DCHECK(reg1.IsValid());
280 return (!reg2.IsValid() || reg2.IsSameFormat(reg1)) &&
281 (!reg3.IsValid() || reg3.IsSameFormat(reg1)) &&
282 (!reg4.IsValid() || reg4.IsSameFormat(reg1));
283 }
284
285 bool AreConsecutive(const VRegister& reg1, const VRegister& reg2,
286 const VRegister& reg3, const VRegister& reg4) {
287 DCHECK(reg1.IsValid());
288 if (!reg2.IsValid()) {
289 DCHECK(!reg3.IsValid() && !reg4.IsValid());
290 return true;
291 } else if (reg2.code() != ((reg1.code() + 1) % kNumberOfVRegisters)) {
292 return false;
293 }
294
295 if (!reg3.IsValid()) {
296 DCHECK(!reg4.IsValid());
297 return true;
298 } else if (reg3.code() != ((reg2.code() + 1) % kNumberOfVRegisters)) {
299 return false;
300 }
301
302 if (!reg4.IsValid()) {
303 return true;
304 } else if (reg4.code() != ((reg3.code() + 1) % kNumberOfVRegisters)) {
305 return false;
306 }
307
308 return true;
309 }
279 310
280 void Immediate::InitializeHandle(Handle<Object> handle) { 311 void Immediate::InitializeHandle(Handle<Object> handle) {
281 AllowDeferredHandleDereference using_raw_address; 312 AllowDeferredHandleDereference using_raw_address;
282 313
283 // Verify all Objects referred by code are NOT in new space. 314 // Verify all Objects referred by code are NOT in new space.
284 Object* obj = *handle; 315 Object* obj = *handle;
285 if (obj->IsHeapObject()) { 316 if (obj->IsHeapObject()) {
286 value_ = reinterpret_cast<intptr_t>(handle.location()); 317 value_ = reinterpret_cast<intptr_t>(handle.location());
287 rmode_ = RelocInfo::EMBEDDED_OBJECT; 318 rmode_ = RelocInfo::EMBEDDED_OBJECT;
288 } else { 319 } else {
(...skipping 1476 matching lines...) Expand 10 before | Expand all | Expand 10 after
1765 } 1796 }
1766 1797
1767 void Assembler::stlxrh(const Register& rs, const Register& rt, 1798 void Assembler::stlxrh(const Register& rs, const Register& rt,
1768 const Register& rn) { 1799 const Register& rn) {
1769 DCHECK(rs.Is32Bits()); 1800 DCHECK(rs.Is32Bits());
1770 DCHECK(rt.Is32Bits()); 1801 DCHECK(rt.Is32Bits());
1771 DCHECK(rn.Is64Bits()); 1802 DCHECK(rn.Is64Bits());
1772 Emit(STLXR_h | Rs(rs) | Rt2(x31) | RnSP(rn) | Rt(rt)); 1803 Emit(STLXR_h | Rs(rs) | Rt2(x31) | RnSP(rn) | Rt(rt));
1773 } 1804 }
1774 1805
1806 void Assembler::NEON3DifferentL(const VRegister& vd, const VRegister& vn,
1807 const VRegister& vm, NEON3DifferentOp vop) {
1808 DCHECK(AreSameFormat(vn, vm));
1809 DCHECK((vn.Is1H() && vd.Is1S()) || (vn.Is1S() && vd.Is1D()) ||
1810 (vn.Is8B() && vd.Is8H()) || (vn.Is4H() && vd.Is4S()) ||
1811 (vn.Is2S() && vd.Is2D()) || (vn.Is16B() && vd.Is8H()) ||
1812 (vn.Is8H() && vd.Is4S()) || (vn.Is4S() && vd.Is2D()));
1813 Instr format, op = vop;
1814 if (vd.IsScalar()) {
1815 op |= NEON_Q | NEONScalar;
1816 format = SFormat(vn);
1817 } else {
1818 format = VFormat(vn);
1819 }
1820 Emit(format | op | Rm(vm) | Rn(vn) | Rd(vd));
1821 }
1822
1823 void Assembler::NEON3DifferentW(const VRegister& vd, const VRegister& vn,
1824 const VRegister& vm, NEON3DifferentOp vop) {
1825 DCHECK(AreSameFormat(vd, vn));
1826 DCHECK((vm.Is8B() && vd.Is8H()) || (vm.Is4H() && vd.Is4S()) ||
1827 (vm.Is2S() && vd.Is2D()) || (vm.Is16B() && vd.Is8H()) ||
1828 (vm.Is8H() && vd.Is4S()) || (vm.Is4S() && vd.Is2D()));
1829 Emit(VFormat(vm) | vop | Rm(vm) | Rn(vn) | Rd(vd));
1830 }
1831
1832 void Assembler::NEON3DifferentHN(const VRegister& vd, const VRegister& vn,
1833 const VRegister& vm, NEON3DifferentOp vop) {
1834 DCHECK(AreSameFormat(vm, vn));
1835 DCHECK((vd.Is8B() && vn.Is8H()) || (vd.Is4H() && vn.Is4S()) ||
1836 (vd.Is2S() && vn.Is2D()) || (vd.Is16B() && vn.Is8H()) ||
1837 (vd.Is8H() && vn.Is4S()) || (vd.Is4S() && vn.Is2D()));
1838 Emit(VFormat(vd) | vop | Rm(vm) | Rn(vn) | Rd(vd));
1839 }
1840
1841 #define NEON_3DIFF_LONG_LIST(V) \
1842 V(pmull, NEON_PMULL, vn.IsVector() && vn.Is8B()) \
1843 V(pmull2, NEON_PMULL2, vn.IsVector() && vn.Is16B()) \
1844 V(saddl, NEON_SADDL, vn.IsVector() && vn.IsD()) \
1845 V(saddl2, NEON_SADDL2, vn.IsVector() && vn.IsQ()) \
1846 V(sabal, NEON_SABAL, vn.IsVector() && vn.IsD()) \
1847 V(sabal2, NEON_SABAL2, vn.IsVector() && vn.IsQ()) \
1848 V(uabal, NEON_UABAL, vn.IsVector() && vn.IsD()) \
1849 V(uabal2, NEON_UABAL2, vn.IsVector() && vn.IsQ()) \
1850 V(sabdl, NEON_SABDL, vn.IsVector() && vn.IsD()) \
1851 V(sabdl2, NEON_SABDL2, vn.IsVector() && vn.IsQ()) \
1852 V(uabdl, NEON_UABDL, vn.IsVector() && vn.IsD()) \
1853 V(uabdl2, NEON_UABDL2, vn.IsVector() && vn.IsQ()) \
1854 V(smlal, NEON_SMLAL, vn.IsVector() && vn.IsD()) \
1855 V(smlal2, NEON_SMLAL2, vn.IsVector() && vn.IsQ()) \
1856 V(umlal, NEON_UMLAL, vn.IsVector() && vn.IsD()) \
1857 V(umlal2, NEON_UMLAL2, vn.IsVector() && vn.IsQ()) \
1858 V(smlsl, NEON_SMLSL, vn.IsVector() && vn.IsD()) \
1859 V(smlsl2, NEON_SMLSL2, vn.IsVector() && vn.IsQ()) \
1860 V(umlsl, NEON_UMLSL, vn.IsVector() && vn.IsD()) \
1861 V(umlsl2, NEON_UMLSL2, vn.IsVector() && vn.IsQ()) \
1862 V(smull, NEON_SMULL, vn.IsVector() && vn.IsD()) \
1863 V(smull2, NEON_SMULL2, vn.IsVector() && vn.IsQ()) \
1864 V(umull, NEON_UMULL, vn.IsVector() && vn.IsD()) \
1865 V(umull2, NEON_UMULL2, vn.IsVector() && vn.IsQ()) \
1866 V(ssubl, NEON_SSUBL, vn.IsVector() && vn.IsD()) \
1867 V(ssubl2, NEON_SSUBL2, vn.IsVector() && vn.IsQ()) \
1868 V(uaddl, NEON_UADDL, vn.IsVector() && vn.IsD()) \
1869 V(uaddl2, NEON_UADDL2, vn.IsVector() && vn.IsQ()) \
1870 V(usubl, NEON_USUBL, vn.IsVector() && vn.IsD()) \
1871 V(usubl2, NEON_USUBL2, vn.IsVector() && vn.IsQ()) \
1872 V(sqdmlal, NEON_SQDMLAL, vn.Is1H() || vn.Is1S() || vn.Is4H() || vn.Is2S()) \
1873 V(sqdmlal2, NEON_SQDMLAL2, vn.Is1H() || vn.Is1S() || vn.Is8H() || vn.Is4S()) \
1874 V(sqdmlsl, NEON_SQDMLSL, vn.Is1H() || vn.Is1S() || vn.Is4H() || vn.Is2S()) \
1875 V(sqdmlsl2, NEON_SQDMLSL2, vn.Is1H() || vn.Is1S() || vn.Is8H() || vn.Is4S()) \
1876 V(sqdmull, NEON_SQDMULL, vn.Is1H() || vn.Is1S() || vn.Is4H() || vn.Is2S()) \
1877 V(sqdmull2, NEON_SQDMULL2, vn.Is1H() || vn.Is1S() || vn.Is8H() || vn.Is4S())
1878
1879 #define DEFINE_ASM_FUNC(FN, OP, AS) \
1880 void Assembler::FN(const VRegister& vd, const VRegister& vn, \
1881 const VRegister& vm) { \
1882 DCHECK(AS); \
1883 NEON3DifferentL(vd, vn, vm, OP); \
1884 }
1885 NEON_3DIFF_LONG_LIST(DEFINE_ASM_FUNC)
1886 #undef DEFINE_ASM_FUNC
1887
1888 #define NEON_3DIFF_HN_LIST(V) \
1889 V(addhn, NEON_ADDHN, vd.IsD()) \
1890 V(addhn2, NEON_ADDHN2, vd.IsQ()) \
1891 V(raddhn, NEON_RADDHN, vd.IsD()) \
1892 V(raddhn2, NEON_RADDHN2, vd.IsQ()) \
1893 V(subhn, NEON_SUBHN, vd.IsD()) \
1894 V(subhn2, NEON_SUBHN2, vd.IsQ()) \
1895 V(rsubhn, NEON_RSUBHN, vd.IsD()) \
1896 V(rsubhn2, NEON_RSUBHN2, vd.IsQ())
1897
1898 #define DEFINE_ASM_FUNC(FN, OP, AS) \
1899 void Assembler::FN(const VRegister& vd, const VRegister& vn, \
1900 const VRegister& vm) { \
1901 DCHECK(AS); \
1902 NEON3DifferentHN(vd, vn, vm, OP); \
1903 }
1904 NEON_3DIFF_HN_LIST(DEFINE_ASM_FUNC)
1905 #undef DEFINE_ASM_FUNC
1906
1907 void Assembler::NEONPerm(const VRegister& vd, const VRegister& vn,
1908 const VRegister& vm, NEONPermOp op) {
1909 DCHECK(AreSameFormat(vd, vn, vm));
1910 DCHECK(!vd.Is1D());
1911 Emit(VFormat(vd) | op | Rm(vm) | Rn(vn) | Rd(vd));
1912 }
1913
1914 void Assembler::trn1(const VRegister& vd, const VRegister& vn,
1915 const VRegister& vm) {
1916 NEONPerm(vd, vn, vm, NEON_TRN1);
1917 }
1918
1919 void Assembler::trn2(const VRegister& vd, const VRegister& vn,
1920 const VRegister& vm) {
1921 NEONPerm(vd, vn, vm, NEON_TRN2);
1922 }
1923
1924 void Assembler::uzp1(const VRegister& vd, const VRegister& vn,
1925 const VRegister& vm) {
1926 NEONPerm(vd, vn, vm, NEON_UZP1);
1927 }
1928
1929 void Assembler::uzp2(const VRegister& vd, const VRegister& vn,
1930 const VRegister& vm) {
1931 NEONPerm(vd, vn, vm, NEON_UZP2);
1932 }
1933
1934 void Assembler::zip1(const VRegister& vd, const VRegister& vn,
1935 const VRegister& vm) {
1936 NEONPerm(vd, vn, vm, NEON_ZIP1);
1937 }
1938
1939 void Assembler::zip2(const VRegister& vd, const VRegister& vn,
1940 const VRegister& vm) {
1941 NEONPerm(vd, vn, vm, NEON_ZIP2);
1942 }
1943
1944 void Assembler::NEONShiftImmediate(const VRegister& vd, const VRegister& vn,
1945 NEONShiftImmediateOp op, int immh_immb) {
1946 DCHECK(AreSameFormat(vd, vn));
1947 Instr q, scalar;
1948 if (vn.IsScalar()) {
1949 q = NEON_Q;
1950 scalar = NEONScalar;
1951 } else {
1952 q = vd.IsD() ? 0 : NEON_Q;
1953 scalar = 0;
1954 }
1955 Emit(q | op | scalar | immh_immb | Rn(vn) | Rd(vd));
1956 }
1957
1958 void Assembler::NEONShiftLeftImmediate(const VRegister& vd, const VRegister& vn,
1959 int shift, NEONShiftImmediateOp op) {
1960 int laneSizeInBits = vn.LaneSizeInBits();
1961 DCHECK((shift >= 0) && (shift < laneSizeInBits));
1962 NEONShiftImmediate(vd, vn, op, (laneSizeInBits + shift) << 16);
1963 }
1964
1965 void Assembler::NEONShiftRightImmediate(const VRegister& vd,
1966 const VRegister& vn, int shift,
1967 NEONShiftImmediateOp op) {
1968 int laneSizeInBits = vn.LaneSizeInBits();
1969 DCHECK((shift >= 1) && (shift <= laneSizeInBits));
1970 NEONShiftImmediate(vd, vn, op, ((2 * laneSizeInBits) - shift) << 16);
1971 }
1972
1973 void Assembler::NEONShiftImmediateL(const VRegister& vd, const VRegister& vn,
1974 int shift, NEONShiftImmediateOp op) {
1975 int laneSizeInBits = vn.LaneSizeInBits();
1976 DCHECK((shift >= 0) && (shift < laneSizeInBits));
1977 int immh_immb = (laneSizeInBits + shift) << 16;
1978
1979 DCHECK((vn.Is8B() && vd.Is8H()) || (vn.Is4H() && vd.Is4S()) ||
1980 (vn.Is2S() && vd.Is2D()) || (vn.Is16B() && vd.Is8H()) ||
1981 (vn.Is8H() && vd.Is4S()) || (vn.Is4S() && vd.Is2D()));
1982 Instr q;
1983 q = vn.IsD() ? 0 : NEON_Q;
1984 Emit(q | op | immh_immb | Rn(vn) | Rd(vd));
1985 }
1986
1987 void Assembler::NEONShiftImmediateN(const VRegister& vd, const VRegister& vn,
1988 int shift, NEONShiftImmediateOp op) {
1989 Instr q, scalar;
1990 int laneSizeInBits = vd.LaneSizeInBits();
1991 DCHECK((shift >= 1) && (shift <= laneSizeInBits));
1992 int immh_immb = (2 * laneSizeInBits - shift) << 16;
1993
1994 if (vn.IsScalar()) {
1995 DCHECK((vd.Is1B() && vn.Is1H()) || (vd.Is1H() && vn.Is1S()) ||
1996 (vd.Is1S() && vn.Is1D()));
1997 q = NEON_Q;
1998 scalar = NEONScalar;
1999 } else {
2000 DCHECK((vd.Is8B() && vn.Is8H()) || (vd.Is4H() && vn.Is4S()) ||
2001 (vd.Is2S() && vn.Is2D()) || (vd.Is16B() && vn.Is8H()) ||
2002 (vd.Is8H() && vn.Is4S()) || (vd.Is4S() && vn.Is2D()));
2003 scalar = 0;
2004 q = vd.IsD() ? 0 : NEON_Q;
2005 }
2006 Emit(q | op | scalar | immh_immb | Rn(vn) | Rd(vd));
2007 }
2008
2009 void Assembler::shl(const VRegister& vd, const VRegister& vn, int shift) {
2010 DCHECK(vd.IsVector() || vd.Is1D());
2011 NEONShiftLeftImmediate(vd, vn, shift, NEON_SHL);
2012 }
2013
2014 void Assembler::sli(const VRegister& vd, const VRegister& vn, int shift) {
2015 DCHECK(vd.IsVector() || vd.Is1D());
2016 NEONShiftLeftImmediate(vd, vn, shift, NEON_SLI);
2017 }
2018
2019 void Assembler::sqshl(const VRegister& vd, const VRegister& vn, int shift) {
2020 NEONShiftLeftImmediate(vd, vn, shift, NEON_SQSHL_imm);
2021 }
2022
2023 void Assembler::sqshlu(const VRegister& vd, const VRegister& vn, int shift) {
2024 NEONShiftLeftImmediate(vd, vn, shift, NEON_SQSHLU);
2025 }
2026
2027 void Assembler::uqshl(const VRegister& vd, const VRegister& vn, int shift) {
2028 NEONShiftLeftImmediate(vd, vn, shift, NEON_UQSHL_imm);
2029 }
2030
2031 void Assembler::sshll(const VRegister& vd, const VRegister& vn, int shift) {
2032 DCHECK(vn.IsD());
2033 NEONShiftImmediateL(vd, vn, shift, NEON_SSHLL);
2034 }
2035
2036 void Assembler::sshll2(const VRegister& vd, const VRegister& vn, int shift) {
2037 DCHECK(vn.IsQ());
2038 NEONShiftImmediateL(vd, vn, shift, NEON_SSHLL);
2039 }
2040
2041 void Assembler::sxtl(const VRegister& vd, const VRegister& vn) {
2042 sshll(vd, vn, 0);
2043 }
2044
2045 void Assembler::sxtl2(const VRegister& vd, const VRegister& vn) {
2046 sshll2(vd, vn, 0);
2047 }
2048
2049 void Assembler::ushll(const VRegister& vd, const VRegister& vn, int shift) {
2050 DCHECK(vn.IsD());
2051 NEONShiftImmediateL(vd, vn, shift, NEON_USHLL);
2052 }
2053
2054 void Assembler::ushll2(const VRegister& vd, const VRegister& vn, int shift) {
2055 DCHECK(vn.IsQ());
2056 NEONShiftImmediateL(vd, vn, shift, NEON_USHLL);
2057 }
2058
2059 void Assembler::uxtl(const VRegister& vd, const VRegister& vn) {
2060 ushll(vd, vn, 0);
2061 }
2062
2063 void Assembler::uxtl2(const VRegister& vd, const VRegister& vn) {
2064 ushll2(vd, vn, 0);
2065 }
2066
2067 void Assembler::sri(const VRegister& vd, const VRegister& vn, int shift) {
2068 DCHECK(vd.IsVector() || vd.Is1D());
2069 NEONShiftRightImmediate(vd, vn, shift, NEON_SRI);
2070 }
2071
2072 void Assembler::sshr(const VRegister& vd, const VRegister& vn, int shift) {
2073 DCHECK(vd.IsVector() || vd.Is1D());
2074 NEONShiftRightImmediate(vd, vn, shift, NEON_SSHR);
2075 }
2076
2077 void Assembler::ushr(const VRegister& vd, const VRegister& vn, int shift) {
2078 DCHECK(vd.IsVector() || vd.Is1D());
2079 NEONShiftRightImmediate(vd, vn, shift, NEON_USHR);
2080 }
2081
2082 void Assembler::srshr(const VRegister& vd, const VRegister& vn, int shift) {
2083 DCHECK(vd.IsVector() || vd.Is1D());
2084 NEONShiftRightImmediate(vd, vn, shift, NEON_SRSHR);
2085 }
2086
2087 void Assembler::urshr(const VRegister& vd, const VRegister& vn, int shift) {
2088 DCHECK(vd.IsVector() || vd.Is1D());
2089 NEONShiftRightImmediate(vd, vn, shift, NEON_URSHR);
2090 }
2091
2092 void Assembler::ssra(const VRegister& vd, const VRegister& vn, int shift) {
2093 DCHECK(vd.IsVector() || vd.Is1D());
2094 NEONShiftRightImmediate(vd, vn, shift, NEON_SSRA);
2095 }
2096
2097 void Assembler::usra(const VRegister& vd, const VRegister& vn, int shift) {
2098 DCHECK(vd.IsVector() || vd.Is1D());
2099 NEONShiftRightImmediate(vd, vn, shift, NEON_USRA);
2100 }
2101
2102 void Assembler::srsra(const VRegister& vd, const VRegister& vn, int shift) {
2103 DCHECK(vd.IsVector() || vd.Is1D());
2104 NEONShiftRightImmediate(vd, vn, shift, NEON_SRSRA);
2105 }
2106
2107 void Assembler::ursra(const VRegister& vd, const VRegister& vn, int shift) {
2108 DCHECK(vd.IsVector() || vd.Is1D());
2109 NEONShiftRightImmediate(vd, vn, shift, NEON_URSRA);
2110 }
2111
2112 void Assembler::shrn(const VRegister& vd, const VRegister& vn, int shift) {
2113 DCHECK(vn.IsVector() && vd.IsD());
2114 NEONShiftImmediateN(vd, vn, shift, NEON_SHRN);
2115 }
2116
2117 void Assembler::shrn2(const VRegister& vd, const VRegister& vn, int shift) {
2118 DCHECK(vn.IsVector() && vd.IsQ());
2119 NEONShiftImmediateN(vd, vn, shift, NEON_SHRN);
2120 }
2121
2122 void Assembler::rshrn(const VRegister& vd, const VRegister& vn, int shift) {
2123 DCHECK(vn.IsVector() && vd.IsD());
2124 NEONShiftImmediateN(vd, vn, shift, NEON_RSHRN);
2125 }
2126
2127 void Assembler::rshrn2(const VRegister& vd, const VRegister& vn, int shift) {
2128 DCHECK(vn.IsVector() && vd.IsQ());
2129 NEONShiftImmediateN(vd, vn, shift, NEON_RSHRN);
2130 }
2131
2132 void Assembler::sqshrn(const VRegister& vd, const VRegister& vn, int shift) {
2133 DCHECK(vd.IsD() || (vn.IsScalar() && vd.IsScalar()));
2134 NEONShiftImmediateN(vd, vn, shift, NEON_SQSHRN);
2135 }
2136
2137 void Assembler::sqshrn2(const VRegister& vd, const VRegister& vn, int shift) {
2138 DCHECK(vn.IsVector() && vd.IsQ());
2139 NEONShiftImmediateN(vd, vn, shift, NEON_SQSHRN);
2140 }
2141
2142 void Assembler::sqrshrn(const VRegister& vd, const VRegister& vn, int shift) {
2143 DCHECK(vd.IsD() || (vn.IsScalar() && vd.IsScalar()));
2144 NEONShiftImmediateN(vd, vn, shift, NEON_SQRSHRN);
2145 }
2146
2147 void Assembler::sqrshrn2(const VRegister& vd, const VRegister& vn, int shift) {
2148 DCHECK(vn.IsVector() && vd.IsQ());
2149 NEONShiftImmediateN(vd, vn, shift, NEON_SQRSHRN);
2150 }
2151
2152 void Assembler::sqshrun(const VRegister& vd, const VRegister& vn, int shift) {
2153 DCHECK(vd.IsD() || (vn.IsScalar() && vd.IsScalar()));
2154 NEONShiftImmediateN(vd, vn, shift, NEON_SQSHRUN);
2155 }
2156
2157 void Assembler::sqshrun2(const VRegister& vd, const VRegister& vn, int shift) {
2158 DCHECK(vn.IsVector() && vd.IsQ());
2159 NEONShiftImmediateN(vd, vn, shift, NEON_SQSHRUN);
2160 }
2161
2162 void Assembler::sqrshrun(const VRegister& vd, const VRegister& vn, int shift) {
2163 DCHECK(vd.IsD() || (vn.IsScalar() && vd.IsScalar()));
2164 NEONShiftImmediateN(vd, vn, shift, NEON_SQRSHRUN);
2165 }
2166
2167 void Assembler::sqrshrun2(const VRegister& vd, const VRegister& vn, int shift) {
2168 DCHECK(vn.IsVector() && vd.IsQ());
2169 NEONShiftImmediateN(vd, vn, shift, NEON_SQRSHRUN);
2170 }
2171
2172 void Assembler::uqshrn(const VRegister& vd, const VRegister& vn, int shift) {
2173 DCHECK(vd.IsD() || (vn.IsScalar() && vd.IsScalar()));
2174 NEONShiftImmediateN(vd, vn, shift, NEON_UQSHRN);
2175 }
2176
2177 void Assembler::uqshrn2(const VRegister& vd, const VRegister& vn, int shift) {
2178 DCHECK(vn.IsVector() && vd.IsQ());
2179 NEONShiftImmediateN(vd, vn, shift, NEON_UQSHRN);
2180 }
2181
2182 void Assembler::uqrshrn(const VRegister& vd, const VRegister& vn, int shift) {
2183 DCHECK(vd.IsD() || (vn.IsScalar() && vd.IsScalar()));
2184 NEONShiftImmediateN(vd, vn, shift, NEON_UQRSHRN);
2185 }
2186
2187 void Assembler::uqrshrn2(const VRegister& vd, const VRegister& vn, int shift) {
2188 DCHECK(vn.IsVector() && vd.IsQ());
2189 NEONShiftImmediateN(vd, vn, shift, NEON_UQRSHRN);
2190 }
2191
2192 void Assembler::uaddw(const VRegister& vd, const VRegister& vn,
2193 const VRegister& vm) {
2194 DCHECK(vm.IsD());
2195 NEON3DifferentW(vd, vn, vm, NEON_UADDW);
2196 }
2197
2198 void Assembler::uaddw2(const VRegister& vd, const VRegister& vn,
2199 const VRegister& vm) {
2200 DCHECK(vm.IsQ());
2201 NEON3DifferentW(vd, vn, vm, NEON_UADDW2);
2202 }
2203
2204 void Assembler::saddw(const VRegister& vd, const VRegister& vn,
2205 const VRegister& vm) {
2206 DCHECK(vm.IsD());
2207 NEON3DifferentW(vd, vn, vm, NEON_SADDW);
2208 }
2209
2210 void Assembler::saddw2(const VRegister& vd, const VRegister& vn,
2211 const VRegister& vm) {
2212 DCHECK(vm.IsQ());
2213 NEON3DifferentW(vd, vn, vm, NEON_SADDW2);
2214 }
2215
2216 void Assembler::usubw(const VRegister& vd, const VRegister& vn,
2217 const VRegister& vm) {
2218 DCHECK(vm.IsD());
2219 NEON3DifferentW(vd, vn, vm, NEON_USUBW);
2220 }
2221
2222 void Assembler::usubw2(const VRegister& vd, const VRegister& vn,
2223 const VRegister& vm) {
2224 DCHECK(vm.IsQ());
2225 NEON3DifferentW(vd, vn, vm, NEON_USUBW2);
2226 }
2227
2228 void Assembler::ssubw(const VRegister& vd, const VRegister& vn,
2229 const VRegister& vm) {
2230 DCHECK(vm.IsD());
2231 NEON3DifferentW(vd, vn, vm, NEON_SSUBW);
2232 }
2233
2234 void Assembler::ssubw2(const VRegister& vd, const VRegister& vn,
2235 const VRegister& vm) {
2236 DCHECK(vm.IsQ());
2237 NEON3DifferentW(vd, vn, vm, NEON_SSUBW2);
2238 }
2239
1775 void Assembler::mov(const Register& rd, const Register& rm) { 2240 void Assembler::mov(const Register& rd, const Register& rm) {
1776 // Moves involving the stack pointer are encoded as add immediate with 2241 // Moves involving the stack pointer are encoded as add immediate with
1777 // second operand of zero. Otherwise, orr with first operand zr is 2242 // second operand of zero. Otherwise, orr with first operand zr is
1778 // used. 2243 // used.
1779 if (rd.IsSP() || rm.IsSP()) { 2244 if (rd.IsSP() || rm.IsSP()) {
1780 add(rd, rm, 0); 2245 add(rd, rm, 0);
1781 } else { 2246 } else {
1782 orr(rd, AppropriateZeroRegFor(rd), rm); 2247 orr(rd, AppropriateZeroRegFor(rd), rm);
1783 } 2248 }
1784 } 2249 }
1785 2250
2251 void Assembler::ins(const VRegister& vd, int vd_index, const Register& rn) {
2252 // We support vd arguments of the form vd.VxT() or vd.T(), where x is the
2253 // number of lanes, and T is b, h, s or d.
2254 int lane_size = vd.LaneSizeInBytes();
2255 NEONFormatField format;
2256 switch (lane_size) {
2257 case 1:
2258 format = NEON_16B;
2259 DCHECK(rn.IsW());
2260 break;
2261 case 2:
2262 format = NEON_8H;
2263 DCHECK(rn.IsW());
2264 break;
2265 case 4:
2266 format = NEON_4S;
2267 DCHECK(rn.IsW());
2268 break;
2269 default:
2270 DCHECK_EQ(lane_size, 8);
2271 DCHECK(rn.IsX());
2272 format = NEON_2D;
2273 break;
2274 }
2275
2276 DCHECK((0 <= vd_index) &&
2277 (vd_index < LaneCountFromFormat(static_cast<VectorFormat>(format))));
2278 Emit(NEON_INS_GENERAL | ImmNEON5(format, vd_index) | Rn(rn) | Rd(vd));
2279 }
2280
2281 void Assembler::mov(const Register& rd, const VRegister& vn, int vn_index) {
2282 DCHECK_GE(vn.SizeInBytes(), 4);
2283 umov(rd, vn, vn_index);
2284 }
2285
2286 void Assembler::smov(const Register& rd, const VRegister& vn, int vn_index) {
2287 // We support vn arguments of the form vn.VxT() or vn.T(), where x is the
2288 // number of lanes, and T is b, h, s.
2289 int lane_size = vn.LaneSizeInBytes();
2290 NEONFormatField format;
2291 Instr q = 0;
2292 switch (lane_size) {
2293 case 1:
2294 format = NEON_16B;
2295 break;
2296 case 2:
2297 format = NEON_8H;
2298 break;
2299 default:
2300 DCHECK_EQ(lane_size, 4);
2301 DCHECK(rd.IsX());
2302 format = NEON_4S;
2303 break;
2304 }
2305 q = rd.IsW() ? 0 : NEON_Q;
2306 DCHECK((0 <= vn_index) &&
2307 (vn_index < LaneCountFromFormat(static_cast<VectorFormat>(format))));
2308 Emit(q | NEON_SMOV | ImmNEON5(format, vn_index) | Rn(vn) | Rd(rd));
2309 }
2310
2311 void Assembler::cls(const VRegister& vd, const VRegister& vn) {
2312 DCHECK(AreSameFormat(vd, vn));
2313 DCHECK(!vd.Is1D() && !vd.Is2D());
2314 Emit(VFormat(vn) | NEON_CLS | Rn(vn) | Rd(vd));
2315 }
2316
2317 void Assembler::clz(const VRegister& vd, const VRegister& vn) {
2318 DCHECK(AreSameFormat(vd, vn));
2319 DCHECK(!vd.Is1D() && !vd.Is2D());
2320 Emit(VFormat(vn) | NEON_CLZ | Rn(vn) | Rd(vd));
2321 }
2322
2323 void Assembler::cnt(const VRegister& vd, const VRegister& vn) {
2324 DCHECK(AreSameFormat(vd, vn));
2325 DCHECK(vd.Is8B() || vd.Is16B());
2326 Emit(VFormat(vn) | NEON_CNT | Rn(vn) | Rd(vd));
2327 }
2328
2329 void Assembler::rev16(const VRegister& vd, const VRegister& vn) {
2330 DCHECK(AreSameFormat(vd, vn));
2331 DCHECK(vd.Is8B() || vd.Is16B());
2332 Emit(VFormat(vn) | NEON_REV16 | Rn(vn) | Rd(vd));
2333 }
2334
2335 void Assembler::rev32(const VRegister& vd, const VRegister& vn) {
2336 DCHECK(AreSameFormat(vd, vn));
2337 DCHECK(vd.Is8B() || vd.Is16B() || vd.Is4H() || vd.Is8H());
2338 Emit(VFormat(vn) | NEON_REV32 | Rn(vn) | Rd(vd));
2339 }
2340
2341 void Assembler::rev64(const VRegister& vd, const VRegister& vn) {
2342 DCHECK(AreSameFormat(vd, vn));
2343 DCHECK(!vd.Is1D() && !vd.Is2D());
2344 Emit(VFormat(vn) | NEON_REV64 | Rn(vn) | Rd(vd));
2345 }
2346
2347 void Assembler::ursqrte(const VRegister& vd, const VRegister& vn) {
2348 DCHECK(AreSameFormat(vd, vn));
2349 DCHECK(vd.Is2S() || vd.Is4S());
2350 Emit(VFormat(vn) | NEON_URSQRTE | Rn(vn) | Rd(vd));
2351 }
2352
2353 void Assembler::urecpe(const VRegister& vd, const VRegister& vn) {
2354 DCHECK(AreSameFormat(vd, vn));
2355 DCHECK(vd.Is2S() || vd.Is4S());
2356 Emit(VFormat(vn) | NEON_URECPE | Rn(vn) | Rd(vd));
2357 }
2358
2359 void Assembler::NEONAddlp(const VRegister& vd, const VRegister& vn,
2360 NEON2RegMiscOp op) {
2361 DCHECK((op == NEON_SADDLP) || (op == NEON_UADDLP) || (op == NEON_SADALP) ||
2362 (op == NEON_UADALP));
2363
2364 DCHECK((vn.Is8B() && vd.Is4H()) || (vn.Is4H() && vd.Is2S()) ||
2365 (vn.Is2S() && vd.Is1D()) || (vn.Is16B() && vd.Is8H()) ||
2366 (vn.Is8H() && vd.Is4S()) || (vn.Is4S() && vd.Is2D()));
2367 Emit(VFormat(vn) | op | Rn(vn) | Rd(vd));
2368 }
2369
2370 void Assembler::saddlp(const VRegister& vd, const VRegister& vn) {
2371 NEONAddlp(vd, vn, NEON_SADDLP);
2372 }
2373
2374 void Assembler::uaddlp(const VRegister& vd, const VRegister& vn) {
2375 NEONAddlp(vd, vn, NEON_UADDLP);
2376 }
2377
2378 void Assembler::sadalp(const VRegister& vd, const VRegister& vn) {
2379 NEONAddlp(vd, vn, NEON_SADALP);
2380 }
2381
2382 void Assembler::uadalp(const VRegister& vd, const VRegister& vn) {
2383 NEONAddlp(vd, vn, NEON_UADALP);
2384 }
2385
2386 void Assembler::NEONAcrossLanesL(const VRegister& vd, const VRegister& vn,
2387 NEONAcrossLanesOp op) {
2388 DCHECK((vn.Is8B() && vd.Is1H()) || (vn.Is16B() && vd.Is1H()) ||
2389 (vn.Is4H() && vd.Is1S()) || (vn.Is8H() && vd.Is1S()) ||
2390 (vn.Is4S() && vd.Is1D()));
2391 Emit(VFormat(vn) | op | Rn(vn) | Rd(vd));
2392 }
2393
2394 void Assembler::saddlv(const VRegister& vd, const VRegister& vn) {
2395 NEONAcrossLanesL(vd, vn, NEON_SADDLV);
2396 }
2397
2398 void Assembler::uaddlv(const VRegister& vd, const VRegister& vn) {
2399 NEONAcrossLanesL(vd, vn, NEON_UADDLV);
2400 }
2401
2402 void Assembler::NEONAcrossLanes(const VRegister& vd, const VRegister& vn,
2403 NEONAcrossLanesOp op) {
2404 DCHECK((vn.Is8B() && vd.Is1B()) || (vn.Is16B() && vd.Is1B()) ||
2405 (vn.Is4H() && vd.Is1H()) || (vn.Is8H() && vd.Is1H()) ||
2406 (vn.Is4S() && vd.Is1S()));
2407 if ((op & NEONAcrossLanesFPFMask) == NEONAcrossLanesFPFixed) {
2408 Emit(FPFormat(vn) | op | Rn(vn) | Rd(vd));
2409 } else {
2410 Emit(VFormat(vn) | op | Rn(vn) | Rd(vd));
2411 }
2412 }
2413
2414 #define NEON_ACROSSLANES_LIST(V) \
2415 V(fmaxv, NEON_FMAXV, vd.Is1S()) \
2416 V(fminv, NEON_FMINV, vd.Is1S()) \
2417 V(fmaxnmv, NEON_FMAXNMV, vd.Is1S()) \
2418 V(fminnmv, NEON_FMINNMV, vd.Is1S()) \
2419 V(addv, NEON_ADDV, true) \
2420 V(smaxv, NEON_SMAXV, true) \
2421 V(sminv, NEON_SMINV, true) \
2422 V(umaxv, NEON_UMAXV, true) \
2423 V(uminv, NEON_UMINV, true)
2424
2425 #define DEFINE_ASM_FUNC(FN, OP, AS) \
2426 void Assembler::FN(const VRegister& vd, const VRegister& vn) { \
2427 DCHECK(AS); \
2428 NEONAcrossLanes(vd, vn, OP); \
2429 }
2430 NEON_ACROSSLANES_LIST(DEFINE_ASM_FUNC)
2431 #undef DEFINE_ASM_FUNC
2432
2433 void Assembler::mov(const VRegister& vd, int vd_index, const Register& rn) {
2434 ins(vd, vd_index, rn);
2435 }
2436
2437 void Assembler::umov(const Register& rd, const VRegister& vn, int vn_index) {
2438 // We support vn arguments of the form vn.VxT() or vn.T(), where x is the
2439 // number of lanes, and T is b, h, s or d.
2440 int lane_size = vn.LaneSizeInBytes();
2441 NEONFormatField format;
2442 Instr q = 0;
2443 switch (lane_size) {
2444 case 1:
2445 format = NEON_16B;
2446 DCHECK(rd.IsW());
2447 break;
2448 case 2:
2449 format = NEON_8H;
2450 DCHECK(rd.IsW());
2451 break;
2452 case 4:
2453 format = NEON_4S;
2454 DCHECK(rd.IsW());
2455 break;
2456 default:
2457 DCHECK_EQ(lane_size, 8);
2458 DCHECK(rd.IsX());
2459 format = NEON_2D;
2460 q = NEON_Q;
2461 break;
2462 }
2463
2464 DCHECK((0 <= vn_index) &&
2465 (vn_index < LaneCountFromFormat(static_cast<VectorFormat>(format))));
2466 Emit(q | NEON_UMOV | ImmNEON5(format, vn_index) | Rn(vn) | Rd(rd));
2467 }
2468
2469 void Assembler::mov(const VRegister& vd, const VRegister& vn, int vn_index) {
2470 DCHECK(vd.IsScalar());
2471 dup(vd, vn, vn_index);
2472 }
2473
2474 void Assembler::dup(const VRegister& vd, const Register& rn) {
2475 DCHECK(!vd.Is1D());
2476 DCHECK_EQ(vd.Is2D(), rn.IsX());
2477 Instr q = vd.IsD() ? 0 : NEON_Q;
2478 Emit(q | NEON_DUP_GENERAL | ImmNEON5(VFormat(vd), 0) | Rn(rn) | Rd(vd));
2479 }
2480
2481 void Assembler::ins(const VRegister& vd, int vd_index, const VRegister& vn,
2482 int vn_index) {
2483 DCHECK(AreSameFormat(vd, vn));
2484 // We support vd arguments of the form vd.VxT() or vd.T(), where x is the
2485 // number of lanes, and T is b, h, s or d.
2486 int lane_size = vd.LaneSizeInBytes();
2487 NEONFormatField format;
2488 switch (lane_size) {
2489 case 1:
2490 format = NEON_16B;
2491 break;
2492 case 2:
2493 format = NEON_8H;
2494 break;
2495 case 4:
2496 format = NEON_4S;
2497 break;
2498 default:
2499 DCHECK_EQ(lane_size, 8);
2500 format = NEON_2D;
2501 break;
2502 }
2503
2504 DCHECK((0 <= vd_index) &&
2505 (vd_index < LaneCountFromFormat(static_cast<VectorFormat>(format))));
2506 DCHECK((0 <= vn_index) &&
2507 (vn_index < LaneCountFromFormat(static_cast<VectorFormat>(format))));
2508 Emit(NEON_INS_ELEMENT | ImmNEON5(format, vd_index) |
2509 ImmNEON4(format, vn_index) | Rn(vn) | Rd(vd));
2510 }
2511
2512 void Assembler::NEONTable(const VRegister& vd, const VRegister& vn,
2513 const VRegister& vm, NEONTableOp op) {
2514 DCHECK(vd.Is16B() || vd.Is8B());
2515 DCHECK(vn.Is16B());
2516 DCHECK(AreSameFormat(vd, vm));
2517 Emit(op | (vd.IsQ() ? NEON_Q : 0) | Rm(vm) | Rn(vn) | Rd(vd));
2518 }
2519
2520 void Assembler::tbl(const VRegister& vd, const VRegister& vn,
2521 const VRegister& vm) {
2522 NEONTable(vd, vn, vm, NEON_TBL_1v);
2523 }
2524
2525 void Assembler::tbl(const VRegister& vd, const VRegister& vn,
2526 const VRegister& vn2, const VRegister& vm) {
2527 USE(vn2);
2528 DCHECK(AreSameFormat(vn, vn2));
2529 DCHECK(AreConsecutive(vn, vn2));
2530 NEONTable(vd, vn, vm, NEON_TBL_2v);
2531 }
2532
2533 void Assembler::tbl(const VRegister& vd, const VRegister& vn,
2534 const VRegister& vn2, const VRegister& vn3,
2535 const VRegister& vm) {
2536 USE(vn2);
2537 USE(vn3);
2538 DCHECK(AreSameFormat(vn, vn2, vn3));
2539 DCHECK(AreConsecutive(vn, vn2, vn3));
2540 NEONTable(vd, vn, vm, NEON_TBL_3v);
2541 }
2542
2543 void Assembler::tbl(const VRegister& vd, const VRegister& vn,
2544 const VRegister& vn2, const VRegister& vn3,
2545 const VRegister& vn4, const VRegister& vm) {
2546 USE(vn2);
2547 USE(vn3);
2548 USE(vn4);
2549 DCHECK(AreSameFormat(vn, vn2, vn3, vn4));
2550 DCHECK(AreConsecutive(vn, vn2, vn3, vn4));
2551 NEONTable(vd, vn, vm, NEON_TBL_4v);
2552 }
2553
2554 void Assembler::tbx(const VRegister& vd, const VRegister& vn,
2555 const VRegister& vm) {
2556 NEONTable(vd, vn, vm, NEON_TBX_1v);
2557 }
2558
2559 void Assembler::tbx(const VRegister& vd, const VRegister& vn,
2560 const VRegister& vn2, const VRegister& vm) {
2561 USE(vn2);
2562 DCHECK(AreSameFormat(vn, vn2));
2563 DCHECK(AreConsecutive(vn, vn2));
2564 NEONTable(vd, vn, vm, NEON_TBX_2v);
2565 }
2566
2567 void Assembler::tbx(const VRegister& vd, const VRegister& vn,
2568 const VRegister& vn2, const VRegister& vn3,
2569 const VRegister& vm) {
2570 USE(vn2);
2571 USE(vn3);
2572 DCHECK(AreSameFormat(vn, vn2, vn3));
2573 DCHECK(AreConsecutive(vn, vn2, vn3));
2574 NEONTable(vd, vn, vm, NEON_TBX_3v);
2575 }
2576
2577 void Assembler::tbx(const VRegister& vd, const VRegister& vn,
2578 const VRegister& vn2, const VRegister& vn3,
2579 const VRegister& vn4, const VRegister& vm) {
2580 USE(vn2);
2581 USE(vn3);
2582 USE(vn4);
2583 DCHECK(AreSameFormat(vn, vn2, vn3, vn4));
2584 DCHECK(AreConsecutive(vn, vn2, vn3, vn4));
2585 NEONTable(vd, vn, vm, NEON_TBX_4v);
2586 }
2587
2588 void Assembler::mov(const VRegister& vd, int vd_index, const VRegister& vn,
2589 int vn_index) {
2590 ins(vd, vd_index, vn, vn_index);
2591 }
1786 2592
1787 void Assembler::mvn(const Register& rd, const Operand& operand) { 2593 void Assembler::mvn(const Register& rd, const Operand& operand) {
1788 orn(rd, AppropriateZeroRegFor(rd), operand); 2594 orn(rd, AppropriateZeroRegFor(rd), operand);
1789 } 2595 }
1790 2596
1791
1792 void Assembler::mrs(const Register& rt, SystemRegister sysreg) { 2597 void Assembler::mrs(const Register& rt, SystemRegister sysreg) {
1793 DCHECK(rt.Is64Bits()); 2598 DCHECK(rt.Is64Bits());
1794 Emit(MRS | ImmSystemRegister(sysreg) | Rt(rt)); 2599 Emit(MRS | ImmSystemRegister(sysreg) | Rt(rt));
1795 } 2600 }
1796 2601
1797
1798 void Assembler::msr(SystemRegister sysreg, const Register& rt) { 2602 void Assembler::msr(SystemRegister sysreg, const Register& rt) {
1799 DCHECK(rt.Is64Bits()); 2603 DCHECK(rt.Is64Bits());
1800 Emit(MSR | Rt(rt) | ImmSystemRegister(sysreg)); 2604 Emit(MSR | Rt(rt) | ImmSystemRegister(sysreg));
1801 } 2605 }
1802 2606
1803 2607 void Assembler::hint(SystemHint code) { Emit(HINT | ImmHint(code) | Rt(xzr)); }
1804 void Assembler::hint(SystemHint code) { 2608
1805 Emit(HINT | ImmHint(code) | Rt(xzr)); 2609 // NEON structure loads and stores.
1806 } 2610 Instr Assembler::LoadStoreStructAddrModeField(const MemOperand& addr) {
1807 2611 Instr addr_field = RnSP(addr.base());
2612
2613 if (addr.IsPostIndex()) {
2614 static_assert(NEONLoadStoreMultiStructPostIndex ==
2615 static_cast<NEONLoadStoreMultiStructPostIndexOp>(
2616 NEONLoadStoreSingleStructPostIndex),
2617 "Opcodes must match for NEON post index memop.");
2618
2619 addr_field |= NEONLoadStoreMultiStructPostIndex;
2620 if (addr.offset() == 0) {
2621 addr_field |= RmNot31(addr.regoffset());
2622 } else {
2623 // The immediate post index addressing mode is indicated by rm = 31.
2624 // The immediate is implied by the number of vector registers used.
2625 addr_field |= (0x1f << Rm_offset);
2626 }
2627 } else {
2628 DCHECK(addr.IsImmediateOffset() && (addr.offset() == 0));
2629 }
2630 return addr_field;
2631 }
2632
2633 void Assembler::LoadStoreStructVerify(const VRegister& vt,
2634 const MemOperand& addr, Instr op) {
2635 #ifdef DEBUG
2636 // Assert that addressing mode is either offset (with immediate 0), post
2637 // index by immediate of the size of the register list, or post index by a
2638 // value in a core register.
2639 if (addr.IsImmediateOffset()) {
2640 DCHECK_EQ(addr.offset(), 0);
2641 } else {
2642 int offset = vt.SizeInBytes();
2643 switch (op) {
2644 case NEON_LD1_1v:
2645 case NEON_ST1_1v:
2646 offset *= 1;
2647 break;
2648 case NEONLoadStoreSingleStructLoad1:
2649 case NEONLoadStoreSingleStructStore1:
2650 case NEON_LD1R:
2651 offset = (offset / vt.LaneCount()) * 1;
2652 break;
2653
2654 case NEON_LD1_2v:
2655 case NEON_ST1_2v:
2656 case NEON_LD2:
2657 case NEON_ST2:
2658 offset *= 2;
2659 break;
2660 case NEONLoadStoreSingleStructLoad2:
2661 case NEONLoadStoreSingleStructStore2:
2662 case NEON_LD2R:
2663 offset = (offset / vt.LaneCount()) * 2;
2664 break;
2665
2666 case NEON_LD1_3v:
2667 case NEON_ST1_3v:
2668 case NEON_LD3:
2669 case NEON_ST3:
2670 offset *= 3;
2671 break;
2672 case NEONLoadStoreSingleStructLoad3:
2673 case NEONLoadStoreSingleStructStore3:
2674 case NEON_LD3R:
2675 offset = (offset / vt.LaneCount()) * 3;
2676 break;
2677
2678 case NEON_LD1_4v:
2679 case NEON_ST1_4v:
2680 case NEON_LD4:
2681 case NEON_ST4:
2682 offset *= 4;
2683 break;
2684 case NEONLoadStoreSingleStructLoad4:
2685 case NEONLoadStoreSingleStructStore4:
2686 case NEON_LD4R:
2687 offset = (offset / vt.LaneCount()) * 4;
2688 break;
2689 default:
2690 UNREACHABLE();
2691 }
2692 DCHECK(!addr.regoffset().Is(NoReg) || addr.offset() == offset);
2693 }
2694 #else
2695 USE(vt);
2696 USE(addr);
2697 USE(op);
2698 #endif
2699 }
2700
2701 void Assembler::LoadStoreStruct(const VRegister& vt, const MemOperand& addr,
2702 NEONLoadStoreMultiStructOp op) {
2703 LoadStoreStructVerify(vt, addr, op);
2704 DCHECK(vt.IsVector() || vt.Is1D());
2705 Emit(op | LoadStoreStructAddrModeField(addr) | LSVFormat(vt) | Rt(vt));
2706 }
2707
2708 void Assembler::LoadStoreStructSingleAllLanes(const VRegister& vt,
2709 const MemOperand& addr,
2710 NEONLoadStoreSingleStructOp op) {
2711 LoadStoreStructVerify(vt, addr, op);
2712 Emit(op | LoadStoreStructAddrModeField(addr) | LSVFormat(vt) | Rt(vt));
2713 }
2714
2715 void Assembler::ld1(const VRegister& vt, const MemOperand& src) {
2716 LoadStoreStruct(vt, src, NEON_LD1_1v);
2717 }
2718
2719 void Assembler::ld1(const VRegister& vt, const VRegister& vt2,
2720 const MemOperand& src) {
2721 USE(vt2);
2722 DCHECK(AreSameFormat(vt, vt2));
2723 DCHECK(AreConsecutive(vt, vt2));
2724 LoadStoreStruct(vt, src, NEON_LD1_2v);
2725 }
2726
2727 void Assembler::ld1(const VRegister& vt, const VRegister& vt2,
2728 const VRegister& vt3, const MemOperand& src) {
2729 USE(vt2);
2730 USE(vt3);
2731 DCHECK(AreSameFormat(vt, vt2, vt3));
2732 DCHECK(AreConsecutive(vt, vt2, vt3));
2733 LoadStoreStruct(vt, src, NEON_LD1_3v);
2734 }
2735
2736 void Assembler::ld1(const VRegister& vt, const VRegister& vt2,
2737 const VRegister& vt3, const VRegister& vt4,
2738 const MemOperand& src) {
2739 USE(vt2);
2740 USE(vt3);
2741 USE(vt4);
2742 DCHECK(AreSameFormat(vt, vt2, vt3, vt4));
2743 DCHECK(AreConsecutive(vt, vt2, vt3, vt4));
2744 LoadStoreStruct(vt, src, NEON_LD1_4v);
2745 }
2746
2747 void Assembler::ld2(const VRegister& vt, const VRegister& vt2,
2748 const MemOperand& src) {
2749 USE(vt2);
2750 DCHECK(AreSameFormat(vt, vt2));
2751 DCHECK(AreConsecutive(vt, vt2));
2752 LoadStoreStruct(vt, src, NEON_LD2);
2753 }
2754
2755 void Assembler::ld2(const VRegister& vt, const VRegister& vt2, int lane,
2756 const MemOperand& src) {
2757 USE(vt2);
2758 DCHECK(AreSameFormat(vt, vt2));
2759 DCHECK(AreConsecutive(vt, vt2));
2760 LoadStoreStructSingle(vt, lane, src, NEONLoadStoreSingleStructLoad2);
2761 }
2762
2763 void Assembler::ld2r(const VRegister& vt, const VRegister& vt2,
2764 const MemOperand& src) {
2765 USE(vt2);
2766 DCHECK(AreSameFormat(vt, vt2));
2767 DCHECK(AreConsecutive(vt, vt2));
2768 LoadStoreStructSingleAllLanes(vt, src, NEON_LD2R);
2769 }
2770
2771 void Assembler::ld3(const VRegister& vt, const VRegister& vt2,
2772 const VRegister& vt3, const MemOperand& src) {
2773 USE(vt2);
2774 USE(vt3);
2775 DCHECK(AreSameFormat(vt, vt2, vt3));
2776 DCHECK(AreConsecutive(vt, vt2, vt3));
2777 LoadStoreStruct(vt, src, NEON_LD3);
2778 }
2779
2780 void Assembler::ld3(const VRegister& vt, const VRegister& vt2,
2781 const VRegister& vt3, int lane, const MemOperand& src) {
2782 USE(vt2);
2783 USE(vt3);
2784 DCHECK(AreSameFormat(vt, vt2, vt3));
2785 DCHECK(AreConsecutive(vt, vt2, vt3));
2786 LoadStoreStructSingle(vt, lane, src, NEONLoadStoreSingleStructLoad3);
2787 }
2788
2789 void Assembler::ld3r(const VRegister& vt, const VRegister& vt2,
2790 const VRegister& vt3, const MemOperand& src) {
2791 USE(vt2);
2792 USE(vt3);
2793 DCHECK(AreSameFormat(vt, vt2, vt3));
2794 DCHECK(AreConsecutive(vt, vt2, vt3));
2795 LoadStoreStructSingleAllLanes(vt, src, NEON_LD3R);
2796 }
2797
2798 void Assembler::ld4(const VRegister& vt, const VRegister& vt2,
2799 const VRegister& vt3, const VRegister& vt4,
2800 const MemOperand& src) {
2801 USE(vt2);
2802 USE(vt3);
2803 USE(vt4);
2804 DCHECK(AreSameFormat(vt, vt2, vt3, vt4));
2805 DCHECK(AreConsecutive(vt, vt2, vt3, vt4));
2806 LoadStoreStruct(vt, src, NEON_LD4);
2807 }
2808
2809 void Assembler::ld4(const VRegister& vt, const VRegister& vt2,
2810 const VRegister& vt3, const VRegister& vt4, int lane,
2811 const MemOperand& src) {
2812 USE(vt2);
2813 USE(vt3);
2814 USE(vt4);
2815 DCHECK(AreSameFormat(vt, vt2, vt3, vt4));
2816 DCHECK(AreConsecutive(vt, vt2, vt3, vt4));
2817 LoadStoreStructSingle(vt, lane, src, NEONLoadStoreSingleStructLoad4);
2818 }
2819
2820 void Assembler::ld4r(const VRegister& vt, const VRegister& vt2,
2821 const VRegister& vt3, const VRegister& vt4,
2822 const MemOperand& src) {
2823 USE(vt2);
2824 USE(vt3);
2825 USE(vt4);
2826 DCHECK(AreSameFormat(vt, vt2, vt3, vt4));
2827 DCHECK(AreConsecutive(vt, vt2, vt3, vt4));
2828 LoadStoreStructSingleAllLanes(vt, src, NEON_LD4R);
2829 }
2830
2831 void Assembler::st1(const VRegister& vt, const MemOperand& src) {
2832 LoadStoreStruct(vt, src, NEON_ST1_1v);
2833 }
2834
2835 void Assembler::st1(const VRegister& vt, const VRegister& vt2,
2836 const MemOperand& src) {
2837 USE(vt2);
2838 DCHECK(AreSameFormat(vt, vt2));
2839 DCHECK(AreConsecutive(vt, vt2));
2840 LoadStoreStruct(vt, src, NEON_ST1_2v);
2841 }
2842
2843 void Assembler::st1(const VRegister& vt, const VRegister& vt2,
2844 const VRegister& vt3, const MemOperand& src) {
2845 USE(vt2);
2846 USE(vt3);
2847 DCHECK(AreSameFormat(vt, vt2, vt3));
2848 DCHECK(AreConsecutive(vt, vt2, vt3));
2849 LoadStoreStruct(vt, src, NEON_ST1_3v);
2850 }
2851
2852 void Assembler::st1(const VRegister& vt, const VRegister& vt2,
2853 const VRegister& vt3, const VRegister& vt4,
2854 const MemOperand& src) {
2855 USE(vt2);
2856 USE(vt3);
2857 USE(vt4);
2858 DCHECK(AreSameFormat(vt, vt2, vt3, vt4));
2859 DCHECK(AreConsecutive(vt, vt2, vt3, vt4));
2860 LoadStoreStruct(vt, src, NEON_ST1_4v);
2861 }
2862
2863 void Assembler::st2(const VRegister& vt, const VRegister& vt2,
2864 const MemOperand& dst) {
2865 USE(vt2);
2866 DCHECK(AreSameFormat(vt, vt2));
2867 DCHECK(AreConsecutive(vt, vt2));
2868 LoadStoreStruct(vt, dst, NEON_ST2);
2869 }
2870
2871 void Assembler::st2(const VRegister& vt, const VRegister& vt2, int lane,
2872 const MemOperand& dst) {
2873 USE(vt2);
2874 DCHECK(AreSameFormat(vt, vt2));
2875 DCHECK(AreConsecutive(vt, vt2));
2876 LoadStoreStructSingle(vt, lane, dst, NEONLoadStoreSingleStructStore2);
2877 }
2878
2879 void Assembler::st3(const VRegister& vt, const VRegister& vt2,
2880 const VRegister& vt3, const MemOperand& dst) {
2881 USE(vt2);
2882 USE(vt3);
2883 DCHECK(AreSameFormat(vt, vt2, vt3));
2884 DCHECK(AreConsecutive(vt, vt2, vt3));
2885 LoadStoreStruct(vt, dst, NEON_ST3);
2886 }
2887
2888 void Assembler::st3(const VRegister& vt, const VRegister& vt2,
2889 const VRegister& vt3, int lane, const MemOperand& dst) {
2890 USE(vt2);
2891 USE(vt3);
2892 DCHECK(AreSameFormat(vt, vt2, vt3));
2893 DCHECK(AreConsecutive(vt, vt2, vt3));
2894 LoadStoreStructSingle(vt, lane, dst, NEONLoadStoreSingleStructStore3);
2895 }
2896
2897 void Assembler::st4(const VRegister& vt, const VRegister& vt2,
2898 const VRegister& vt3, const VRegister& vt4,
2899 const MemOperand& dst) {
2900 USE(vt2);
2901 USE(vt3);
2902 USE(vt4);
2903 DCHECK(AreSameFormat(vt, vt2, vt3, vt4));
2904 DCHECK(AreConsecutive(vt, vt2, vt3, vt4));
2905 LoadStoreStruct(vt, dst, NEON_ST4);
2906 }
2907
2908 void Assembler::st4(const VRegister& vt, const VRegister& vt2,
2909 const VRegister& vt3, const VRegister& vt4, int lane,
2910 const MemOperand& dst) {
2911 USE(vt2);
2912 USE(vt3);
2913 USE(vt4);
2914 DCHECK(AreSameFormat(vt, vt2, vt3, vt4));
2915 DCHECK(AreConsecutive(vt, vt2, vt3, vt4));
2916 LoadStoreStructSingle(vt, lane, dst, NEONLoadStoreSingleStructStore4);
2917 }
2918
2919 void Assembler::LoadStoreStructSingle(const VRegister& vt, uint32_t lane,
2920 const MemOperand& addr,
2921 NEONLoadStoreSingleStructOp op) {
2922 LoadStoreStructVerify(vt, addr, op);
2923
2924 // We support vt arguments of the form vt.VxT() or vt.T(), where x is the
2925 // number of lanes, and T is b, h, s or d.
2926 unsigned lane_size = vt.LaneSizeInBytes();
2927 DCHECK_LT(lane, kQRegSize / lane_size);
2928
2929 // Lane size is encoded in the opcode field. Lane index is encoded in the Q,
2930 // S and size fields.
2931 lane *= lane_size;
2932
2933 // Encodings for S[0]/D[0] and S[2]/D[1] are distinguished using the least-
2934 // significant bit of the size field, so we increment lane here to account for
2935 // that.
2936 if (lane_size == 8) lane++;
2937
2938 Instr size = (lane << NEONLSSize_offset) & NEONLSSize_mask;
2939 Instr s = (lane << (NEONS_offset - 2)) & NEONS_mask;
2940 Instr q = (lane << (NEONQ_offset - 3)) & NEONQ_mask;
2941
2942 Instr instr = op;
2943 switch (lane_size) {
2944 case 1:
2945 instr |= NEONLoadStoreSingle_b;
2946 break;
2947 case 2:
2948 instr |= NEONLoadStoreSingle_h;
2949 break;
2950 case 4:
2951 instr |= NEONLoadStoreSingle_s;
2952 break;
2953 default:
2954 DCHECK_EQ(lane_size, 8U);
2955 instr |= NEONLoadStoreSingle_d;
2956 }
2957
2958 Emit(instr | LoadStoreStructAddrModeField(addr) | q | size | s | Rt(vt));
2959 }
2960
2961 void Assembler::ld1(const VRegister& vt, int lane, const MemOperand& src) {
2962 LoadStoreStructSingle(vt, lane, src, NEONLoadStoreSingleStructLoad1);
2963 }
2964
2965 void Assembler::ld1r(const VRegister& vt, const MemOperand& src) {
2966 LoadStoreStructSingleAllLanes(vt, src, NEON_LD1R);
2967 }
2968
2969 void Assembler::st1(const VRegister& vt, int lane, const MemOperand& dst) {
2970 LoadStoreStructSingle(vt, lane, dst, NEONLoadStoreSingleStructStore1);
2971 }
1808 2972
1809 void Assembler::dmb(BarrierDomain domain, BarrierType type) { 2973 void Assembler::dmb(BarrierDomain domain, BarrierType type) {
1810 Emit(DMB | ImmBarrierDomain(domain) | ImmBarrierType(type)); 2974 Emit(DMB | ImmBarrierDomain(domain) | ImmBarrierType(type));
1811 } 2975 }
1812 2976
1813
1814 void Assembler::dsb(BarrierDomain domain, BarrierType type) { 2977 void Assembler::dsb(BarrierDomain domain, BarrierType type) {
1815 Emit(DSB | ImmBarrierDomain(domain) | ImmBarrierType(type)); 2978 Emit(DSB | ImmBarrierDomain(domain) | ImmBarrierType(type));
1816 } 2979 }
1817 2980
1818
1819 void Assembler::isb() { 2981 void Assembler::isb() {
1820 Emit(ISB | ImmBarrierDomain(FullSystem) | ImmBarrierType(BarrierAll)); 2982 Emit(ISB | ImmBarrierDomain(FullSystem) | ImmBarrierType(BarrierAll));
1821 } 2983 }
1822 2984
1823 2985 void Assembler::fmov(const VRegister& vd, double imm) {
1824 void Assembler::fmov(FPRegister fd, double imm) { 2986 if (vd.IsScalar()) {
1825 DCHECK(fd.Is64Bits()); 2987 DCHECK(vd.Is1D());
1826 DCHECK(IsImmFP64(imm)); 2988 Emit(FMOV_d_imm | Rd(vd) | ImmFP(imm));
1827 Emit(FMOV_d_imm | Rd(fd) | ImmFP64(imm)); 2989 } else {
1828 } 2990 DCHECK(vd.Is2D());
1829 2991 Instr op = NEONModifiedImmediate_MOVI | NEONModifiedImmediateOpBit;
1830 2992 Emit(NEON_Q | op | ImmNEONFP(imm) | NEONCmode(0xf) | Rd(vd));
1831 void Assembler::fmov(FPRegister fd, float imm) { 2993 }
1832 DCHECK(fd.Is32Bits()); 2994 }
1833 DCHECK(IsImmFP32(imm)); 2995
1834 Emit(FMOV_s_imm | Rd(fd) | ImmFP32(imm)); 2996 void Assembler::fmov(const VRegister& vd, float imm) {
1835 } 2997 if (vd.IsScalar()) {
1836 2998 DCHECK(vd.Is1S());
1837 2999 Emit(FMOV_s_imm | Rd(vd) | ImmFP(imm));
1838 void Assembler::fmov(Register rd, FPRegister fn) { 3000 } else {
1839 DCHECK(rd.SizeInBits() == fn.SizeInBits()); 3001 DCHECK(vd.Is2S() | vd.Is4S());
3002 Instr op = NEONModifiedImmediate_MOVI;
3003 Instr q = vd.Is4S() ? NEON_Q : 0;
3004 Emit(q | op | ImmNEONFP(imm) | NEONCmode(0xf) | Rd(vd));
3005 }
3006 }
3007
3008 void Assembler::fmov(const Register& rd, const VRegister& fn) {
3009 DCHECK_EQ(rd.SizeInBits(), fn.SizeInBits());
1840 FPIntegerConvertOp op = rd.Is32Bits() ? FMOV_ws : FMOV_xd; 3010 FPIntegerConvertOp op = rd.Is32Bits() ? FMOV_ws : FMOV_xd;
1841 Emit(op | Rd(rd) | Rn(fn)); 3011 Emit(op | Rd(rd) | Rn(fn));
1842 } 3012 }
1843 3013
1844 3014 void Assembler::fmov(const VRegister& vd, const Register& rn) {
1845 void Assembler::fmov(FPRegister fd, Register rn) { 3015 DCHECK_EQ(vd.SizeInBits(), rn.SizeInBits());
1846 DCHECK(fd.SizeInBits() == rn.SizeInBits()); 3016 FPIntegerConvertOp op = vd.Is32Bits() ? FMOV_sw : FMOV_dx;
1847 FPIntegerConvertOp op = fd.Is32Bits() ? FMOV_sw : FMOV_dx; 3017 Emit(op | Rd(vd) | Rn(rn));
1848 Emit(op | Rd(fd) | Rn(rn)); 3018 }
1849 } 3019
1850 3020 void Assembler::fmov(const VRegister& vd, const VRegister& vn) {
1851 3021 DCHECK_EQ(vd.SizeInBits(), vn.SizeInBits());
1852 void Assembler::fmov(FPRegister fd, FPRegister fn) { 3022 Emit(FPType(vd) | FMOV | Rd(vd) | Rn(vn));
1853 DCHECK(fd.SizeInBits() == fn.SizeInBits()); 3023 }
1854 Emit(FPType(fd) | FMOV | Rd(fd) | Rn(fn)); 3024
1855 } 3025 void Assembler::fmov(const VRegister& vd, int index, const Register& rn) {
1856 3026 DCHECK((index == 1) && vd.Is1D() && rn.IsX());
1857 3027 USE(index);
1858 void Assembler::fadd(const FPRegister& fd, 3028 Emit(FMOV_d1_x | Rd(vd) | Rn(rn));
1859 const FPRegister& fn, 3029 }
1860 const FPRegister& fm) { 3030
1861 FPDataProcessing2Source(fd, fn, fm, FADD); 3031 void Assembler::fmov(const Register& rd, const VRegister& vn, int index) {
1862 } 3032 DCHECK((index == 1) && vn.Is1D() && rd.IsX());
1863 3033 USE(index);
1864 3034 Emit(FMOV_x_d1 | Rd(rd) | Rn(vn));
1865 void Assembler::fsub(const FPRegister& fd, 3035 }
1866 const FPRegister& fn, 3036
1867 const FPRegister& fm) { 3037 void Assembler::fmadd(const VRegister& fd, const VRegister& fn,
1868 FPDataProcessing2Source(fd, fn, fm, FSUB); 3038 const VRegister& fm, const VRegister& fa) {
1869 }
1870
1871
1872 void Assembler::fmul(const FPRegister& fd,
1873 const FPRegister& fn,
1874 const FPRegister& fm) {
1875 FPDataProcessing2Source(fd, fn, fm, FMUL);
1876 }
1877
1878
1879 void Assembler::fmadd(const FPRegister& fd,
1880 const FPRegister& fn,
1881 const FPRegister& fm,
1882 const FPRegister& fa) {
1883 FPDataProcessing3Source(fd, fn, fm, fa, fd.Is32Bits() ? FMADD_s : FMADD_d); 3039 FPDataProcessing3Source(fd, fn, fm, fa, fd.Is32Bits() ? FMADD_s : FMADD_d);
1884 } 3040 }
1885 3041
1886 3042 void Assembler::fmsub(const VRegister& fd, const VRegister& fn,
1887 void Assembler::fmsub(const FPRegister& fd, 3043 const VRegister& fm, const VRegister& fa) {
1888 const FPRegister& fn,
1889 const FPRegister& fm,
1890 const FPRegister& fa) {
1891 FPDataProcessing3Source(fd, fn, fm, fa, fd.Is32Bits() ? FMSUB_s : FMSUB_d); 3044 FPDataProcessing3Source(fd, fn, fm, fa, fd.Is32Bits() ? FMSUB_s : FMSUB_d);
1892 } 3045 }
1893 3046
1894 3047 void Assembler::fnmadd(const VRegister& fd, const VRegister& fn,
1895 void Assembler::fnmadd(const FPRegister& fd, 3048 const VRegister& fm, const VRegister& fa) {
1896 const FPRegister& fn,
1897 const FPRegister& fm,
1898 const FPRegister& fa) {
1899 FPDataProcessing3Source(fd, fn, fm, fa, fd.Is32Bits() ? FNMADD_s : FNMADD_d); 3049 FPDataProcessing3Source(fd, fn, fm, fa, fd.Is32Bits() ? FNMADD_s : FNMADD_d);
1900 } 3050 }
1901 3051
1902 3052 void Assembler::fnmsub(const VRegister& fd, const VRegister& fn,
1903 void Assembler::fnmsub(const FPRegister& fd, 3053 const VRegister& fm, const VRegister& fa) {
1904 const FPRegister& fn,
1905 const FPRegister& fm,
1906 const FPRegister& fa) {
1907 FPDataProcessing3Source(fd, fn, fm, fa, fd.Is32Bits() ? FNMSUB_s : FNMSUB_d); 3054 FPDataProcessing3Source(fd, fn, fm, fa, fd.Is32Bits() ? FNMSUB_s : FNMSUB_d);
1908 } 3055 }
1909 3056
1910 3057 void Assembler::fnmul(const VRegister& vd, const VRegister& vn,
1911 void Assembler::fdiv(const FPRegister& fd, 3058 const VRegister& vm) {
1912 const FPRegister& fn, 3059 DCHECK(AreSameSizeAndType(vd, vn, vm));
1913 const FPRegister& fm) { 3060 Instr op = vd.Is1S() ? FNMUL_s : FNMUL_d;
1914 FPDataProcessing2Source(fd, fn, fm, FDIV); 3061 Emit(FPType(vd) | op | Rm(vm) | Rn(vn) | Rd(vd));
1915 } 3062 }
1916 3063
1917 3064 void Assembler::fcmp(const VRegister& fn, const VRegister& fm) {
1918 void Assembler::fmax(const FPRegister& fd, 3065 DCHECK_EQ(fn.SizeInBits(), fm.SizeInBits());
1919 const FPRegister& fn,
1920 const FPRegister& fm) {
1921 FPDataProcessing2Source(fd, fn, fm, FMAX);
1922 }
1923
1924
1925 void Assembler::fmaxnm(const FPRegister& fd,
1926 const FPRegister& fn,
1927 const FPRegister& fm) {
1928 FPDataProcessing2Source(fd, fn, fm, FMAXNM);
1929 }
1930
1931
1932 void Assembler::fmin(const FPRegister& fd,
1933 const FPRegister& fn,
1934 const FPRegister& fm) {
1935 FPDataProcessing2Source(fd, fn, fm, FMIN);
1936 }
1937
1938
1939 void Assembler::fminnm(const FPRegister& fd,
1940 const FPRegister& fn,
1941 const FPRegister& fm) {
1942 FPDataProcessing2Source(fd, fn, fm, FMINNM);
1943 }
1944
1945
1946 void Assembler::fabs(const FPRegister& fd,
1947 const FPRegister& fn) {
1948 DCHECK(fd.SizeInBits() == fn.SizeInBits());
1949 FPDataProcessing1Source(fd, fn, FABS);
1950 }
1951
1952
1953 void Assembler::fneg(const FPRegister& fd,
1954 const FPRegister& fn) {
1955 DCHECK(fd.SizeInBits() == fn.SizeInBits());
1956 FPDataProcessing1Source(fd, fn, FNEG);
1957 }
1958
1959
1960 void Assembler::fsqrt(const FPRegister& fd,
1961 const FPRegister& fn) {
1962 DCHECK(fd.SizeInBits() == fn.SizeInBits());
1963 FPDataProcessing1Source(fd, fn, FSQRT);
1964 }
1965
1966
1967 void Assembler::frinta(const FPRegister& fd,
1968 const FPRegister& fn) {
1969 DCHECK(fd.SizeInBits() == fn.SizeInBits());
1970 FPDataProcessing1Source(fd, fn, FRINTA);
1971 }
1972
1973
1974 void Assembler::frintm(const FPRegister& fd,
1975 const FPRegister& fn) {
1976 DCHECK(fd.SizeInBits() == fn.SizeInBits());
1977 FPDataProcessing1Source(fd, fn, FRINTM);
1978 }
1979
1980
1981 void Assembler::frintn(const FPRegister& fd,
1982 const FPRegister& fn) {
1983 DCHECK(fd.SizeInBits() == fn.SizeInBits());
1984 FPDataProcessing1Source(fd, fn, FRINTN);
1985 }
1986
1987
1988 void Assembler::frintp(const FPRegister& fd, const FPRegister& fn) {
1989 DCHECK(fd.SizeInBits() == fn.SizeInBits());
1990 FPDataProcessing1Source(fd, fn, FRINTP);
1991 }
1992
1993
1994 void Assembler::frintz(const FPRegister& fd,
1995 const FPRegister& fn) {
1996 DCHECK(fd.SizeInBits() == fn.SizeInBits());
1997 FPDataProcessing1Source(fd, fn, FRINTZ);
1998 }
1999
2000
2001 void Assembler::fcmp(const FPRegister& fn,
2002 const FPRegister& fm) {
2003 DCHECK(fn.SizeInBits() == fm.SizeInBits());
2004 Emit(FPType(fn) | FCMP | Rm(fm) | Rn(fn)); 3066 Emit(FPType(fn) | FCMP | Rm(fm) | Rn(fn));
2005 } 3067 }
2006 3068
2007 3069 void Assembler::fcmp(const VRegister& fn, double value) {
2008 void Assembler::fcmp(const FPRegister& fn,
2009 double value) {
2010 USE(value); 3070 USE(value);
2011 // Although the fcmp instruction can strictly only take an immediate value of 3071 // Although the fcmp instruction can strictly only take an immediate value of
2012 // +0.0, we don't need to check for -0.0 because the sign of 0.0 doesn't 3072 // +0.0, we don't need to check for -0.0 because the sign of 0.0 doesn't
2013 // affect the result of the comparison. 3073 // affect the result of the comparison.
2014 DCHECK(value == 0.0); 3074 DCHECK_EQ(value, 0.0);
2015 Emit(FPType(fn) | FCMP_zero | Rn(fn)); 3075 Emit(FPType(fn) | FCMP_zero | Rn(fn));
2016 } 3076 }
2017 3077
2018 3078 void Assembler::fccmp(const VRegister& fn, const VRegister& fm,
2019 void Assembler::fccmp(const FPRegister& fn, 3079 StatusFlags nzcv, Condition cond) {
2020 const FPRegister& fm, 3080 DCHECK_EQ(fn.SizeInBits(), fm.SizeInBits());
2021 StatusFlags nzcv,
2022 Condition cond) {
2023 DCHECK(fn.SizeInBits() == fm.SizeInBits());
2024 Emit(FPType(fn) | FCCMP | Rm(fm) | Cond(cond) | Rn(fn) | Nzcv(nzcv)); 3081 Emit(FPType(fn) | FCCMP | Rm(fm) | Cond(cond) | Rn(fn) | Nzcv(nzcv));
2025 } 3082 }
2026 3083
2027 3084 void Assembler::fcsel(const VRegister& fd, const VRegister& fn,
2028 void Assembler::fcsel(const FPRegister& fd, 3085 const VRegister& fm, Condition cond) {
2029 const FPRegister& fn, 3086 DCHECK_EQ(fd.SizeInBits(), fn.SizeInBits());
2030 const FPRegister& fm, 3087 DCHECK_EQ(fd.SizeInBits(), fm.SizeInBits());
2031 Condition cond) {
2032 DCHECK(fd.SizeInBits() == fn.SizeInBits());
2033 DCHECK(fd.SizeInBits() == fm.SizeInBits());
2034 Emit(FPType(fd) | FCSEL | Rm(fm) | Cond(cond) | Rn(fn) | Rd(fd)); 3088 Emit(FPType(fd) | FCSEL | Rm(fm) | Cond(cond) | Rn(fn) | Rd(fd));
2035 } 3089 }
2036 3090
2037 3091 void Assembler::NEONFPConvertToInt(const Register& rd, const VRegister& vn,
2038 void Assembler::FPConvertToInt(const Register& rd, 3092 Instr op) {
2039 const FPRegister& fn, 3093 Emit(SF(rd) | FPType(vn) | op | Rn(vn) | Rd(rd));
2040 FPIntegerConvertOp op) { 3094 }
2041 Emit(SF(rd) | FPType(fn) | op | Rn(fn) | Rd(rd)); 3095
2042 } 3096 void Assembler::NEONFPConvertToInt(const VRegister& vd, const VRegister& vn,
2043 3097 Instr op) {
2044 3098 if (vn.IsScalar()) {
2045 void Assembler::fcvt(const FPRegister& fd, 3099 DCHECK((vd.Is1S() && vn.Is1S()) || (vd.Is1D() && vn.Is1D()));
2046 const FPRegister& fn) { 3100 op |= NEON_Q | NEONScalar;
2047 if (fd.Is64Bits()) { 3101 }
2048 // Convert float to double. 3102 Emit(FPFormat(vn) | op | Rn(vn) | Rd(vd));
2049 DCHECK(fn.Is32Bits()); 3103 }
2050 FPDataProcessing1Source(fd, fn, FCVT_ds); 3104
2051 } else { 3105 void Assembler::fcvt(const VRegister& vd, const VRegister& vn) {
2052 // Convert double to float. 3106 FPDataProcessing1SourceOp op;
2053 DCHECK(fn.Is64Bits()); 3107 if (vd.Is1D()) {
2054 FPDataProcessing1Source(fd, fn, FCVT_sd); 3108 DCHECK(vn.Is1S() || vn.Is1H());
2055 } 3109 op = vn.Is1S() ? FCVT_ds : FCVT_dh;
2056 } 3110 } else if (vd.Is1S()) {
2057 3111 DCHECK(vn.Is1D() || vn.Is1H());
2058 3112 op = vn.Is1D() ? FCVT_sd : FCVT_sh;
2059 void Assembler::fcvtau(const Register& rd, const FPRegister& fn) { 3113 } else {
2060 FPConvertToInt(rd, fn, FCVTAU); 3114 DCHECK(vd.Is1H());
2061 } 3115 DCHECK(vn.Is1D() || vn.Is1S());
2062 3116 op = vn.Is1D() ? FCVT_hd : FCVT_hs;
2063 3117 }
2064 void Assembler::fcvtas(const Register& rd, const FPRegister& fn) { 3118 FPDataProcessing1Source(vd, vn, op);
2065 FPConvertToInt(rd, fn, FCVTAS); 3119 }
2066 } 3120
2067 3121 void Assembler::fcvtl(const VRegister& vd, const VRegister& vn) {
2068 3122 DCHECK((vd.Is4S() && vn.Is4H()) || (vd.Is2D() && vn.Is2S()));
2069 void Assembler::fcvtmu(const Register& rd, const FPRegister& fn) { 3123 Instr format = vd.Is2D() ? (1 << NEONSize_offset) : 0;
2070 FPConvertToInt(rd, fn, FCVTMU); 3124 Emit(format | NEON_FCVTL | Rn(vn) | Rd(vd));
2071 } 3125 }
2072 3126
2073 3127 void Assembler::fcvtl2(const VRegister& vd, const VRegister& vn) {
2074 void Assembler::fcvtms(const Register& rd, const FPRegister& fn) { 3128 DCHECK((vd.Is4S() && vn.Is8H()) || (vd.Is2D() && vn.Is4S()));
2075 FPConvertToInt(rd, fn, FCVTMS); 3129 Instr format = vd.Is2D() ? (1 << NEONSize_offset) : 0;
2076 } 3130 Emit(NEON_Q | format | NEON_FCVTL | Rn(vn) | Rd(vd));
2077 3131 }
2078 3132
2079 void Assembler::fcvtnu(const Register& rd, const FPRegister& fn) { 3133 void Assembler::fcvtn(const VRegister& vd, const VRegister& vn) {
2080 FPConvertToInt(rd, fn, FCVTNU); 3134 DCHECK((vn.Is4S() && vd.Is4H()) || (vn.Is2D() && vd.Is2S()));
2081 } 3135 Instr format = vn.Is2D() ? (1 << NEONSize_offset) : 0;
2082 3136 Emit(format | NEON_FCVTN | Rn(vn) | Rd(vd));
2083 3137 }
2084 void Assembler::fcvtns(const Register& rd, const FPRegister& fn) { 3138
2085 FPConvertToInt(rd, fn, FCVTNS); 3139 void Assembler::fcvtn2(const VRegister& vd, const VRegister& vn) {
2086 } 3140 DCHECK((vn.Is4S() && vd.Is8H()) || (vn.Is2D() && vd.Is4S()));
2087 3141 Instr format = vn.Is2D() ? (1 << NEONSize_offset) : 0;
2088 3142 Emit(NEON_Q | format | NEON_FCVTN | Rn(vn) | Rd(vd));
2089 void Assembler::fcvtzu(const Register& rd, const FPRegister& fn) { 3143 }
2090 FPConvertToInt(rd, fn, FCVTZU); 3144
2091 } 3145 void Assembler::fcvtxn(const VRegister& vd, const VRegister& vn) {
2092 3146 Instr format = 1 << NEONSize_offset;
2093 3147 if (vd.IsScalar()) {
2094 void Assembler::fcvtzs(const Register& rd, const FPRegister& fn) { 3148 DCHECK(vd.Is1S() && vn.Is1D());
2095 FPConvertToInt(rd, fn, FCVTZS); 3149 Emit(format | NEON_FCVTXN_scalar | Rn(vn) | Rd(vd));
2096 } 3150 } else {
2097 3151 DCHECK(vd.Is2S() && vn.Is2D());
2098 3152 Emit(format | NEON_FCVTXN | Rn(vn) | Rd(vd));
2099 void Assembler::scvtf(const FPRegister& fd, 3153 }
2100 const Register& rn, 3154 }
2101 unsigned fbits) { 3155
3156 void Assembler::fcvtxn2(const VRegister& vd, const VRegister& vn) {
3157 DCHECK(vd.Is4S() && vn.Is2D());
3158 Instr format = 1 << NEONSize_offset;
3159 Emit(NEON_Q | format | NEON_FCVTXN | Rn(vn) | Rd(vd));
3160 }
3161
3162 #define NEON_FP2REGMISC_FCVT_LIST(V) \
3163 V(fcvtnu, NEON_FCVTNU, FCVTNU) \
3164 V(fcvtns, NEON_FCVTNS, FCVTNS) \
3165 V(fcvtpu, NEON_FCVTPU, FCVTPU) \
3166 V(fcvtps, NEON_FCVTPS, FCVTPS) \
3167 V(fcvtmu, NEON_FCVTMU, FCVTMU) \
3168 V(fcvtms, NEON_FCVTMS, FCVTMS) \
3169 V(fcvtau, NEON_FCVTAU, FCVTAU) \
3170 V(fcvtas, NEON_FCVTAS, FCVTAS)
3171
3172 #define DEFINE_ASM_FUNCS(FN, VEC_OP, SCA_OP) \
3173 void Assembler::FN(const Register& rd, const VRegister& vn) { \
3174 NEONFPConvertToInt(rd, vn, SCA_OP); \
3175 } \
3176 void Assembler::FN(const VRegister& vd, const VRegister& vn) { \
3177 NEONFPConvertToInt(vd, vn, VEC_OP); \
3178 }
3179 NEON_FP2REGMISC_FCVT_LIST(DEFINE_ASM_FUNCS)
3180 #undef DEFINE_ASM_FUNCS
3181
3182 void Assembler::scvtf(const VRegister& vd, const VRegister& vn, int fbits) {
3183 DCHECK_GE(fbits, 0);
2102 if (fbits == 0) { 3184 if (fbits == 0) {
2103 Emit(SF(rn) | FPType(fd) | SCVTF | Rn(rn) | Rd(fd)); 3185 NEONFP2RegMisc(vd, vn, NEON_SCVTF);
2104 } else { 3186 } else {
2105 Emit(SF(rn) | FPType(fd) | SCVTF_fixed | FPScale(64 - fbits) | Rn(rn) | 3187 DCHECK(vd.Is1D() || vd.Is1S() || vd.Is2D() || vd.Is2S() || vd.Is4S());
2106 Rd(fd)); 3188 NEONShiftRightImmediate(vd, vn, fbits, NEON_SCVTF_imm);
2107 } 3189 }
2108 } 3190 }
2109 3191
2110 3192 void Assembler::ucvtf(const VRegister& vd, const VRegister& vn, int fbits) {
2111 void Assembler::ucvtf(const FPRegister& fd, 3193 DCHECK_GE(fbits, 0);
2112 const Register& rn, 3194 if (fbits == 0) {
2113 unsigned fbits) { 3195 NEONFP2RegMisc(vd, vn, NEON_UCVTF);
3196 } else {
3197 DCHECK(vd.Is1D() || vd.Is1S() || vd.Is2D() || vd.Is2S() || vd.Is4S());
3198 NEONShiftRightImmediate(vd, vn, fbits, NEON_UCVTF_imm);
3199 }
3200 }
3201
3202 void Assembler::scvtf(const VRegister& vd, const Register& rn, int fbits) {
3203 DCHECK_GE(fbits, 0);
3204 if (fbits == 0) {
3205 Emit(SF(rn) | FPType(vd) | SCVTF | Rn(rn) | Rd(vd));
3206 } else {
3207 Emit(SF(rn) | FPType(vd) | SCVTF_fixed | FPScale(64 - fbits) | Rn(rn) |
3208 Rd(vd));
3209 }
3210 }
3211
3212 void Assembler::ucvtf(const VRegister& fd, const Register& rn, int fbits) {
3213 DCHECK_GE(fbits, 0);
2114 if (fbits == 0) { 3214 if (fbits == 0) {
2115 Emit(SF(rn) | FPType(fd) | UCVTF | Rn(rn) | Rd(fd)); 3215 Emit(SF(rn) | FPType(fd) | UCVTF | Rn(rn) | Rd(fd));
2116 } else { 3216 } else {
2117 Emit(SF(rn) | FPType(fd) | UCVTF_fixed | FPScale(64 - fbits) | Rn(rn) | 3217 Emit(SF(rn) | FPType(fd) | UCVTF_fixed | FPScale(64 - fbits) | Rn(rn) |
2118 Rd(fd)); 3218 Rd(fd));
2119 } 3219 }
2120 } 3220 }
2121 3221
3222 void Assembler::NEON3Same(const VRegister& vd, const VRegister& vn,
3223 const VRegister& vm, NEON3SameOp vop) {
3224 DCHECK(AreSameFormat(vd, vn, vm));
3225 DCHECK(vd.IsVector() || !vd.IsQ());
3226
3227 Instr format, op = vop;
3228 if (vd.IsScalar()) {
3229 op |= NEON_Q | NEONScalar;
3230 format = SFormat(vd);
3231 } else {
3232 format = VFormat(vd);
3233 }
3234
3235 Emit(format | op | Rm(vm) | Rn(vn) | Rd(vd));
3236 }
3237
3238 void Assembler::NEONFP3Same(const VRegister& vd, const VRegister& vn,
3239 const VRegister& vm, Instr op) {
3240 DCHECK(AreSameFormat(vd, vn, vm));
3241 Emit(FPFormat(vd) | op | Rm(vm) | Rn(vn) | Rd(vd));
3242 }
3243
3244 #define NEON_FP2REGMISC_LIST(V) \
3245 V(fabs, NEON_FABS, FABS) \
3246 V(fneg, NEON_FNEG, FNEG) \
3247 V(fsqrt, NEON_FSQRT, FSQRT) \
3248 V(frintn, NEON_FRINTN, FRINTN) \
3249 V(frinta, NEON_FRINTA, FRINTA) \
3250 V(frintp, NEON_FRINTP, FRINTP) \
3251 V(frintm, NEON_FRINTM, FRINTM) \
3252 V(frintx, NEON_FRINTX, FRINTX) \
3253 V(frintz, NEON_FRINTZ, FRINTZ) \
3254 V(frinti, NEON_FRINTI, FRINTI) \
3255 V(frsqrte, NEON_FRSQRTE, NEON_FRSQRTE_scalar) \
3256 V(frecpe, NEON_FRECPE, NEON_FRECPE_scalar)
3257
3258 #define DEFINE_ASM_FUNC(FN, VEC_OP, SCA_OP) \
3259 void Assembler::FN(const VRegister& vd, const VRegister& vn) { \
3260 Instr op; \
3261 if (vd.IsScalar()) { \
3262 DCHECK(vd.Is1S() || vd.Is1D()); \
3263 op = SCA_OP; \
3264 } else { \
3265 DCHECK(vd.Is2S() || vd.Is2D() || vd.Is4S()); \
3266 op = VEC_OP; \
3267 } \
3268 NEONFP2RegMisc(vd, vn, op); \
3269 }
3270 NEON_FP2REGMISC_LIST(DEFINE_ASM_FUNC)
3271 #undef DEFINE_ASM_FUNC
3272
3273 void Assembler::shll(const VRegister& vd, const VRegister& vn, int shift) {
3274 DCHECK((vd.Is8H() && vn.Is8B() && shift == 8) ||
3275 (vd.Is4S() && vn.Is4H() && shift == 16) ||
3276 (vd.Is2D() && vn.Is2S() && shift == 32));
3277 USE(shift);
3278 Emit(VFormat(vn) | NEON_SHLL | Rn(vn) | Rd(vd));
3279 }
3280
3281 void Assembler::shll2(const VRegister& vd, const VRegister& vn, int shift) {
3282 USE(shift);
3283 DCHECK((vd.Is8H() && vn.Is16B() && shift == 8) ||
3284 (vd.Is4S() && vn.Is8H() && shift == 16) ||
3285 (vd.Is2D() && vn.Is4S() && shift == 32));
3286 Emit(VFormat(vn) | NEON_SHLL | Rn(vn) | Rd(vd));
3287 }
3288
3289 void Assembler::NEONFP2RegMisc(const VRegister& vd, const VRegister& vn,
3290 NEON2RegMiscOp vop, double value) {
3291 DCHECK(AreSameFormat(vd, vn));
3292 DCHECK_EQ(value, 0.0);
3293 USE(value);
3294
3295 Instr op = vop;
3296 if (vd.IsScalar()) {
3297 DCHECK(vd.Is1S() || vd.Is1D());
3298 op |= NEON_Q | NEONScalar;
3299 } else {
3300 DCHECK(vd.Is2S() || vd.Is2D() || vd.Is4S());
3301 }
3302
3303 Emit(FPFormat(vd) | op | Rn(vn) | Rd(vd));
3304 }
3305
3306 void Assembler::fcmeq(const VRegister& vd, const VRegister& vn, double value) {
3307 NEONFP2RegMisc(vd, vn, NEON_FCMEQ_zero, value);
3308 }
3309
3310 void Assembler::fcmge(const VRegister& vd, const VRegister& vn, double value) {
3311 NEONFP2RegMisc(vd, vn, NEON_FCMGE_zero, value);
3312 }
3313
3314 void Assembler::fcmgt(const VRegister& vd, const VRegister& vn, double value) {
3315 NEONFP2RegMisc(vd, vn, NEON_FCMGT_zero, value);
3316 }
3317
3318 void Assembler::fcmle(const VRegister& vd, const VRegister& vn, double value) {
3319 NEONFP2RegMisc(vd, vn, NEON_FCMLE_zero, value);
3320 }
3321
3322 void Assembler::fcmlt(const VRegister& vd, const VRegister& vn, double value) {
3323 NEONFP2RegMisc(vd, vn, NEON_FCMLT_zero, value);
3324 }
3325
3326 void Assembler::frecpx(const VRegister& vd, const VRegister& vn) {
3327 DCHECK(vd.IsScalar());
3328 DCHECK(AreSameFormat(vd, vn));
3329 DCHECK(vd.Is1S() || vd.Is1D());
3330 Emit(FPFormat(vd) | NEON_FRECPX_scalar | Rn(vn) | Rd(vd));
3331 }
3332
3333 void Assembler::fcvtzs(const Register& rd, const VRegister& vn, int fbits) {
3334 DCHECK(vn.Is1S() || vn.Is1D());
3335 DCHECK((fbits >= 0) && (fbits <= rd.SizeInBits()));
3336 if (fbits == 0) {
3337 Emit(SF(rd) | FPType(vn) | FCVTZS | Rn(vn) | Rd(rd));
3338 } else {
3339 Emit(SF(rd) | FPType(vn) | FCVTZS_fixed | FPScale(64 - fbits) | Rn(vn) |
3340 Rd(rd));
3341 }
3342 }
3343
3344 void Assembler::fcvtzs(const VRegister& vd, const VRegister& vn, int fbits) {
3345 DCHECK_GE(fbits, 0);
3346 if (fbits == 0) {
3347 NEONFP2RegMisc(vd, vn, NEON_FCVTZS);
3348 } else {
3349 DCHECK(vd.Is1D() || vd.Is1S() || vd.Is2D() || vd.Is2S() || vd.Is4S());
3350 NEONShiftRightImmediate(vd, vn, fbits, NEON_FCVTZS_imm);
3351 }
3352 }
3353
3354 void Assembler::fcvtzu(const Register& rd, const VRegister& vn, int fbits) {
3355 DCHECK(vn.Is1S() || vn.Is1D());
3356 DCHECK((fbits >= 0) && (fbits <= rd.SizeInBits()));
3357 if (fbits == 0) {
3358 Emit(SF(rd) | FPType(vn) | FCVTZU | Rn(vn) | Rd(rd));
3359 } else {
3360 Emit(SF(rd) | FPType(vn) | FCVTZU_fixed | FPScale(64 - fbits) | Rn(vn) |
3361 Rd(rd));
3362 }
3363 }
3364
3365 void Assembler::fcvtzu(const VRegister& vd, const VRegister& vn, int fbits) {
3366 DCHECK_GE(fbits, 0);
3367 if (fbits == 0) {
3368 NEONFP2RegMisc(vd, vn, NEON_FCVTZU);
3369 } else {
3370 DCHECK(vd.Is1D() || vd.Is1S() || vd.Is2D() || vd.Is2S() || vd.Is4S());
3371 NEONShiftRightImmediate(vd, vn, fbits, NEON_FCVTZU_imm);
3372 }
3373 }
3374
3375 void Assembler::NEONFP2RegMisc(const VRegister& vd, const VRegister& vn,
3376 Instr op) {
3377 DCHECK(AreSameFormat(vd, vn));
3378 Emit(FPFormat(vd) | op | Rn(vn) | Rd(vd));
3379 }
3380
3381 void Assembler::NEON2RegMisc(const VRegister& vd, const VRegister& vn,
3382 NEON2RegMiscOp vop, int value) {
3383 DCHECK(AreSameFormat(vd, vn));
3384 DCHECK_EQ(value, 0);
3385 USE(value);
3386
3387 Instr format, op = vop;
3388 if (vd.IsScalar()) {
3389 op |= NEON_Q | NEONScalar;
3390 format = SFormat(vd);
3391 } else {
3392 format = VFormat(vd);
3393 }
3394
3395 Emit(format | op | Rn(vn) | Rd(vd));
3396 }
3397
3398 void Assembler::cmeq(const VRegister& vd, const VRegister& vn, int value) {
3399 DCHECK(vd.IsVector() || vd.Is1D());
3400 NEON2RegMisc(vd, vn, NEON_CMEQ_zero, value);
3401 }
3402
3403 void Assembler::cmge(const VRegister& vd, const VRegister& vn, int value) {
3404 DCHECK(vd.IsVector() || vd.Is1D());
3405 NEON2RegMisc(vd, vn, NEON_CMGE_zero, value);
3406 }
3407
3408 void Assembler::cmgt(const VRegister& vd, const VRegister& vn, int value) {
3409 DCHECK(vd.IsVector() || vd.Is1D());
3410 NEON2RegMisc(vd, vn, NEON_CMGT_zero, value);
3411 }
3412
3413 void Assembler::cmle(const VRegister& vd, const VRegister& vn, int value) {
3414 DCHECK(vd.IsVector() || vd.Is1D());
3415 NEON2RegMisc(vd, vn, NEON_CMLE_zero, value);
3416 }
3417
3418 void Assembler::cmlt(const VRegister& vd, const VRegister& vn, int value) {
3419 DCHECK(vd.IsVector() || vd.Is1D());
3420 NEON2RegMisc(vd, vn, NEON_CMLT_zero, value);
3421 }
3422
3423 #define NEON_3SAME_LIST(V) \
3424 V(add, NEON_ADD, vd.IsVector() || vd.Is1D()) \
3425 V(addp, NEON_ADDP, vd.IsVector() || vd.Is1D()) \
3426 V(sub, NEON_SUB, vd.IsVector() || vd.Is1D()) \
3427 V(cmeq, NEON_CMEQ, vd.IsVector() || vd.Is1D()) \
3428 V(cmge, NEON_CMGE, vd.IsVector() || vd.Is1D()) \
3429 V(cmgt, NEON_CMGT, vd.IsVector() || vd.Is1D()) \
3430 V(cmhi, NEON_CMHI, vd.IsVector() || vd.Is1D()) \
3431 V(cmhs, NEON_CMHS, vd.IsVector() || vd.Is1D()) \
3432 V(cmtst, NEON_CMTST, vd.IsVector() || vd.Is1D()) \
3433 V(sshl, NEON_SSHL, vd.IsVector() || vd.Is1D()) \
3434 V(ushl, NEON_USHL, vd.IsVector() || vd.Is1D()) \
3435 V(srshl, NEON_SRSHL, vd.IsVector() || vd.Is1D()) \
3436 V(urshl, NEON_URSHL, vd.IsVector() || vd.Is1D()) \
3437 V(sqdmulh, NEON_SQDMULH, vd.IsLaneSizeH() || vd.IsLaneSizeS()) \
3438 V(sqrdmulh, NEON_SQRDMULH, vd.IsLaneSizeH() || vd.IsLaneSizeS()) \
3439 V(shadd, NEON_SHADD, vd.IsVector() && !vd.IsLaneSizeD()) \
3440 V(uhadd, NEON_UHADD, vd.IsVector() && !vd.IsLaneSizeD()) \
3441 V(srhadd, NEON_SRHADD, vd.IsVector() && !vd.IsLaneSizeD()) \
3442 V(urhadd, NEON_URHADD, vd.IsVector() && !vd.IsLaneSizeD()) \
3443 V(shsub, NEON_SHSUB, vd.IsVector() && !vd.IsLaneSizeD()) \
3444 V(uhsub, NEON_UHSUB, vd.IsVector() && !vd.IsLaneSizeD()) \
3445 V(smax, NEON_SMAX, vd.IsVector() && !vd.IsLaneSizeD()) \
3446 V(smaxp, NEON_SMAXP, vd.IsVector() && !vd.IsLaneSizeD()) \
3447 V(smin, NEON_SMIN, vd.IsVector() && !vd.IsLaneSizeD()) \
3448 V(sminp, NEON_SMINP, vd.IsVector() && !vd.IsLaneSizeD()) \
3449 V(umax, NEON_UMAX, vd.IsVector() && !vd.IsLaneSizeD()) \
3450 V(umaxp, NEON_UMAXP, vd.IsVector() && !vd.IsLaneSizeD()) \
3451 V(umin, NEON_UMIN, vd.IsVector() && !vd.IsLaneSizeD()) \
3452 V(uminp, NEON_UMINP, vd.IsVector() && !vd.IsLaneSizeD()) \
3453 V(saba, NEON_SABA, vd.IsVector() && !vd.IsLaneSizeD()) \
3454 V(sabd, NEON_SABD, vd.IsVector() && !vd.IsLaneSizeD()) \
3455 V(uaba, NEON_UABA, vd.IsVector() && !vd.IsLaneSizeD()) \
3456 V(uabd, NEON_UABD, vd.IsVector() && !vd.IsLaneSizeD()) \
3457 V(mla, NEON_MLA, vd.IsVector() && !vd.IsLaneSizeD()) \
3458 V(mls, NEON_MLS, vd.IsVector() && !vd.IsLaneSizeD()) \
3459 V(mul, NEON_MUL, vd.IsVector() && !vd.IsLaneSizeD()) \
3460 V(and_, NEON_AND, vd.Is8B() || vd.Is16B()) \
3461 V(orr, NEON_ORR, vd.Is8B() || vd.Is16B()) \
3462 V(orn, NEON_ORN, vd.Is8B() || vd.Is16B()) \
3463 V(eor, NEON_EOR, vd.Is8B() || vd.Is16B()) \
3464 V(bic, NEON_BIC, vd.Is8B() || vd.Is16B()) \
3465 V(bit, NEON_BIT, vd.Is8B() || vd.Is16B()) \
3466 V(bif, NEON_BIF, vd.Is8B() || vd.Is16B()) \
3467 V(bsl, NEON_BSL, vd.Is8B() || vd.Is16B()) \
3468 V(pmul, NEON_PMUL, vd.Is8B() || vd.Is16B()) \
3469 V(uqadd, NEON_UQADD, true) \
3470 V(sqadd, NEON_SQADD, true) \
3471 V(uqsub, NEON_UQSUB, true) \
3472 V(sqsub, NEON_SQSUB, true) \
3473 V(sqshl, NEON_SQSHL, true) \
3474 V(uqshl, NEON_UQSHL, true) \
3475 V(sqrshl, NEON_SQRSHL, true) \
3476 V(uqrshl, NEON_UQRSHL, true)
3477
3478 #define DEFINE_ASM_FUNC(FN, OP, AS) \
3479 void Assembler::FN(const VRegister& vd, const VRegister& vn, \
3480 const VRegister& vm) { \
3481 DCHECK(AS); \
3482 NEON3Same(vd, vn, vm, OP); \
3483 }
3484 NEON_3SAME_LIST(DEFINE_ASM_FUNC)
3485 #undef DEFINE_ASM_FUNC
3486
3487 #define NEON_FP3SAME_LIST(V) \
3488 V(fadd, NEON_FADD, FADD) \
3489 V(fsub, NEON_FSUB, FSUB) \
3490 V(fmul, NEON_FMUL, FMUL) \
3491 V(fdiv, NEON_FDIV, FDIV) \
3492 V(fmax, NEON_FMAX, FMAX) \
3493 V(fmaxnm, NEON_FMAXNM, FMAXNM) \
3494 V(fmin, NEON_FMIN, FMIN) \
3495 V(fminnm, NEON_FMINNM, FMINNM) \
3496 V(fmulx, NEON_FMULX, NEON_FMULX_scalar) \
3497 V(frecps, NEON_FRECPS, NEON_FRECPS_scalar) \
3498 V(frsqrts, NEON_FRSQRTS, NEON_FRSQRTS_scalar) \
3499 V(fabd, NEON_FABD, NEON_FABD_scalar) \
3500 V(fmla, NEON_FMLA, 0) \
3501 V(fmls, NEON_FMLS, 0) \
3502 V(facge, NEON_FACGE, NEON_FACGE_scalar) \
3503 V(facgt, NEON_FACGT, NEON_FACGT_scalar) \
3504 V(fcmeq, NEON_FCMEQ, NEON_FCMEQ_scalar) \
3505 V(fcmge, NEON_FCMGE, NEON_FCMGE_scalar) \
3506 V(fcmgt, NEON_FCMGT, NEON_FCMGT_scalar) \
3507 V(faddp, NEON_FADDP, 0) \
3508 V(fmaxp, NEON_FMAXP, 0) \
3509 V(fminp, NEON_FMINP, 0) \
3510 V(fmaxnmp, NEON_FMAXNMP, 0) \
3511 V(fminnmp, NEON_FMINNMP, 0)
3512
3513 #define DEFINE_ASM_FUNC(FN, VEC_OP, SCA_OP) \
3514 void Assembler::FN(const VRegister& vd, const VRegister& vn, \
3515 const VRegister& vm) { \
3516 Instr op; \
3517 if ((SCA_OP != 0) && vd.IsScalar()) { \
3518 DCHECK(vd.Is1S() || vd.Is1D()); \
3519 op = SCA_OP; \
3520 } else { \
3521 DCHECK(vd.IsVector()); \
3522 DCHECK(vd.Is2S() || vd.Is2D() || vd.Is4S()); \
3523 op = VEC_OP; \
3524 } \
3525 NEONFP3Same(vd, vn, vm, op); \
3526 }
3527 NEON_FP3SAME_LIST(DEFINE_ASM_FUNC)
3528 #undef DEFINE_ASM_FUNC
3529
3530 void Assembler::addp(const VRegister& vd, const VRegister& vn) {
3531 DCHECK((vd.Is1D() && vn.Is2D()));
3532 Emit(SFormat(vd) | NEON_ADDP_scalar | Rn(vn) | Rd(vd));
3533 }
3534
3535 void Assembler::faddp(const VRegister& vd, const VRegister& vn) {
3536 DCHECK((vd.Is1S() && vn.Is2S()) || (vd.Is1D() && vn.Is2D()));
3537 Emit(FPFormat(vd) | NEON_FADDP_scalar | Rn(vn) | Rd(vd));
3538 }
3539
3540 void Assembler::fmaxp(const VRegister& vd, const VRegister& vn) {
3541 DCHECK((vd.Is1S() && vn.Is2S()) || (vd.Is1D() && vn.Is2D()));
3542 Emit(FPFormat(vd) | NEON_FMAXP_scalar | Rn(vn) | Rd(vd));
3543 }
3544
3545 void Assembler::fminp(const VRegister& vd, const VRegister& vn) {
3546 DCHECK((vd.Is1S() && vn.Is2S()) || (vd.Is1D() && vn.Is2D()));
3547 Emit(FPFormat(vd) | NEON_FMINP_scalar | Rn(vn) | Rd(vd));
3548 }
3549
3550 void Assembler::fmaxnmp(const VRegister& vd, const VRegister& vn) {
3551 DCHECK((vd.Is1S() && vn.Is2S()) || (vd.Is1D() && vn.Is2D()));
3552 Emit(FPFormat(vd) | NEON_FMAXNMP_scalar | Rn(vn) | Rd(vd));
3553 }
3554
3555 void Assembler::fminnmp(const VRegister& vd, const VRegister& vn) {
3556 DCHECK((vd.Is1S() && vn.Is2S()) || (vd.Is1D() && vn.Is2D()));
3557 Emit(FPFormat(vd) | NEON_FMINNMP_scalar | Rn(vn) | Rd(vd));
3558 }
3559
3560 void Assembler::orr(const VRegister& vd, const int imm8, const int left_shift) {
3561 NEONModifiedImmShiftLsl(vd, imm8, left_shift, NEONModifiedImmediate_ORR);
3562 }
3563
3564 void Assembler::mov(const VRegister& vd, const VRegister& vn) {
3565 DCHECK(AreSameFormat(vd, vn));
3566 if (vd.IsD()) {
3567 orr(vd.V8B(), vn.V8B(), vn.V8B());
3568 } else {
3569 DCHECK(vd.IsQ());
3570 orr(vd.V16B(), vn.V16B(), vn.V16B());
3571 }
3572 }
3573
3574 void Assembler::bic(const VRegister& vd, const int imm8, const int left_shift) {
3575 NEONModifiedImmShiftLsl(vd, imm8, left_shift, NEONModifiedImmediate_BIC);
3576 }
3577
3578 void Assembler::movi(const VRegister& vd, const uint64_t imm, Shift shift,
3579 const int shift_amount) {
3580 DCHECK((shift == LSL) || (shift == MSL));
3581 if (vd.Is2D() || vd.Is1D()) {
3582 DCHECK_EQ(shift_amount, 0);
3583 int imm8 = 0;
3584 for (int i = 0; i < 8; ++i) {
3585 int byte = (imm >> (i * 8)) & 0xff;
3586 DCHECK((byte == 0) || (byte == 0xff));
3587 if (byte == 0xff) {
3588 imm8 |= (1 << i);
3589 }
3590 }
3591 Instr q = vd.Is2D() ? NEON_Q : 0;
3592 Emit(q | NEONModImmOp(1) | NEONModifiedImmediate_MOVI |
3593 ImmNEONabcdefgh(imm8) | NEONCmode(0xe) | Rd(vd));
3594 } else if (shift == LSL) {
3595 NEONModifiedImmShiftLsl(vd, static_cast<int>(imm), shift_amount,
3596 NEONModifiedImmediate_MOVI);
3597 } else {
3598 NEONModifiedImmShiftMsl(vd, static_cast<int>(imm), shift_amount,
3599 NEONModifiedImmediate_MOVI);
3600 }
3601 }
3602
3603 void Assembler::mvn(const VRegister& vd, const VRegister& vn) {
3604 DCHECK(AreSameFormat(vd, vn));
3605 if (vd.IsD()) {
3606 not_(vd.V8B(), vn.V8B());
3607 } else {
3608 DCHECK(vd.IsQ());
3609 not_(vd.V16B(), vn.V16B());
3610 }
3611 }
3612
3613 void Assembler::mvni(const VRegister& vd, const int imm8, Shift shift,
3614 const int shift_amount) {
3615 DCHECK((shift == LSL) || (shift == MSL));
3616 if (shift == LSL) {
3617 NEONModifiedImmShiftLsl(vd, imm8, shift_amount, NEONModifiedImmediate_MVNI);
3618 } else {
3619 NEONModifiedImmShiftMsl(vd, imm8, shift_amount, NEONModifiedImmediate_MVNI);
3620 }
3621 }
3622
3623 void Assembler::NEONFPByElement(const VRegister& vd, const VRegister& vn,
3624 const VRegister& vm, int vm_index,
3625 NEONByIndexedElementOp vop) {
3626 DCHECK(AreSameFormat(vd, vn));
3627 DCHECK((vd.Is2S() && vm.Is1S()) || (vd.Is4S() && vm.Is1S()) ||
3628 (vd.Is1S() && vm.Is1S()) || (vd.Is2D() && vm.Is1D()) ||
3629 (vd.Is1D() && vm.Is1D()));
3630 DCHECK((vm.Is1S() && (vm_index < 4)) || (vm.Is1D() && (vm_index < 2)));
3631
3632 Instr op = vop;
3633 int index_num_bits = vm.Is1S() ? 2 : 1;
3634 if (vd.IsScalar()) {
3635 op |= NEON_Q | NEONScalar;
3636 }
3637
3638 Emit(FPFormat(vd) | op | ImmNEONHLM(vm_index, index_num_bits) | Rm(vm) |
3639 Rn(vn) | Rd(vd));
3640 }
3641
3642 void Assembler::NEONByElement(const VRegister& vd, const VRegister& vn,
3643 const VRegister& vm, int vm_index,
3644 NEONByIndexedElementOp vop) {
3645 DCHECK(AreSameFormat(vd, vn));
3646 DCHECK((vd.Is4H() && vm.Is1H()) || (vd.Is8H() && vm.Is1H()) ||
3647 (vd.Is1H() && vm.Is1H()) || (vd.Is2S() && vm.Is1S()) ||
3648 (vd.Is4S() && vm.Is1S()) || (vd.Is1S() && vm.Is1S()));
3649 DCHECK((vm.Is1H() && (vm.code() < 16) && (vm_index < 8)) ||
3650 (vm.Is1S() && (vm_index < 4)));
3651
3652 Instr format, op = vop;
3653 int index_num_bits = vm.Is1H() ? 3 : 2;
3654 if (vd.IsScalar()) {
3655 op |= NEONScalar | NEON_Q;
3656 format = SFormat(vn);
3657 } else {
3658 format = VFormat(vn);
3659 }
3660 Emit(format | op | ImmNEONHLM(vm_index, index_num_bits) | Rm(vm) | Rn(vn) |
3661 Rd(vd));
3662 }
3663
3664 void Assembler::NEONByElementL(const VRegister& vd, const VRegister& vn,
3665 const VRegister& vm, int vm_index,
3666 NEONByIndexedElementOp vop) {
3667 DCHECK((vd.Is4S() && vn.Is4H() && vm.Is1H()) ||
3668 (vd.Is4S() && vn.Is8H() && vm.Is1H()) ||
3669 (vd.Is1S() && vn.Is1H() && vm.Is1H()) ||
3670 (vd.Is2D() && vn.Is2S() && vm.Is1S()) ||
3671 (vd.Is2D() && vn.Is4S() && vm.Is1S()) ||
3672 (vd.Is1D() && vn.Is1S() && vm.Is1S()));
3673
3674 DCHECK((vm.Is1H() && (vm.code() < 16) && (vm_index < 8)) ||
3675 (vm.Is1S() && (vm_index < 4)));
3676
3677 Instr format, op = vop;
3678 int index_num_bits = vm.Is1H() ? 3 : 2;
3679 if (vd.IsScalar()) {
3680 op |= NEONScalar | NEON_Q;
3681 format = SFormat(vn);
3682 } else {
3683 format = VFormat(vn);
3684 }
3685 Emit(format | op | ImmNEONHLM(vm_index, index_num_bits) | Rm(vm) | Rn(vn) |
3686 Rd(vd));
3687 }
3688
3689 #define NEON_BYELEMENT_LIST(V) \
3690 V(mul, NEON_MUL_byelement, vn.IsVector()) \
3691 V(mla, NEON_MLA_byelement, vn.IsVector()) \
3692 V(mls, NEON_MLS_byelement, vn.IsVector()) \
3693 V(sqdmulh, NEON_SQDMULH_byelement, true) \
3694 V(sqrdmulh, NEON_SQRDMULH_byelement, true)
3695
3696 #define DEFINE_ASM_FUNC(FN, OP, AS) \
3697 void Assembler::FN(const VRegister& vd, const VRegister& vn, \
3698 const VRegister& vm, int vm_index) { \
3699 DCHECK(AS); \
3700 NEONByElement(vd, vn, vm, vm_index, OP); \
3701 }
3702 NEON_BYELEMENT_LIST(DEFINE_ASM_FUNC)
3703 #undef DEFINE_ASM_FUNC
3704
3705 #define NEON_FPBYELEMENT_LIST(V) \
3706 V(fmul, NEON_FMUL_byelement) \
3707 V(fmla, NEON_FMLA_byelement) \
3708 V(fmls, NEON_FMLS_byelement) \
3709 V(fmulx, NEON_FMULX_byelement)
3710
3711 #define DEFINE_ASM_FUNC(FN, OP) \
3712 void Assembler::FN(const VRegister& vd, const VRegister& vn, \
3713 const VRegister& vm, int vm_index) { \
3714 NEONFPByElement(vd, vn, vm, vm_index, OP); \
3715 }
3716 NEON_FPBYELEMENT_LIST(DEFINE_ASM_FUNC)
3717 #undef DEFINE_ASM_FUNC
3718
3719 #define NEON_BYELEMENT_LONG_LIST(V) \
3720 V(sqdmull, NEON_SQDMULL_byelement, vn.IsScalar() || vn.IsD()) \
3721 V(sqdmull2, NEON_SQDMULL_byelement, vn.IsVector() && vn.IsQ()) \
3722 V(sqdmlal, NEON_SQDMLAL_byelement, vn.IsScalar() || vn.IsD()) \
3723 V(sqdmlal2, NEON_SQDMLAL_byelement, vn.IsVector() && vn.IsQ()) \
3724 V(sqdmlsl, NEON_SQDMLSL_byelement, vn.IsScalar() || vn.IsD()) \
3725 V(sqdmlsl2, NEON_SQDMLSL_byelement, vn.IsVector() && vn.IsQ()) \
3726 V(smull, NEON_SMULL_byelement, vn.IsVector() && vn.IsD()) \
3727 V(smull2, NEON_SMULL_byelement, vn.IsVector() && vn.IsQ()) \
3728 V(umull, NEON_UMULL_byelement, vn.IsVector() && vn.IsD()) \
3729 V(umull2, NEON_UMULL_byelement, vn.IsVector() && vn.IsQ()) \
3730 V(smlal, NEON_SMLAL_byelement, vn.IsVector() && vn.IsD()) \
3731 V(smlal2, NEON_SMLAL_byelement, vn.IsVector() && vn.IsQ()) \
3732 V(umlal, NEON_UMLAL_byelement, vn.IsVector() && vn.IsD()) \
3733 V(umlal2, NEON_UMLAL_byelement, vn.IsVector() && vn.IsQ()) \
3734 V(smlsl, NEON_SMLSL_byelement, vn.IsVector() && vn.IsD()) \
3735 V(smlsl2, NEON_SMLSL_byelement, vn.IsVector() && vn.IsQ()) \
3736 V(umlsl, NEON_UMLSL_byelement, vn.IsVector() && vn.IsD()) \
3737 V(umlsl2, NEON_UMLSL_byelement, vn.IsVector() && vn.IsQ())
3738
3739 #define DEFINE_ASM_FUNC(FN, OP, AS) \
3740 void Assembler::FN(const VRegister& vd, const VRegister& vn, \
3741 const VRegister& vm, int vm_index) { \
3742 DCHECK(AS); \
3743 NEONByElementL(vd, vn, vm, vm_index, OP); \
3744 }
3745 NEON_BYELEMENT_LONG_LIST(DEFINE_ASM_FUNC)
3746 #undef DEFINE_ASM_FUNC
3747
3748 void Assembler::suqadd(const VRegister& vd, const VRegister& vn) {
3749 NEON2RegMisc(vd, vn, NEON_SUQADD);
3750 }
3751
3752 void Assembler::usqadd(const VRegister& vd, const VRegister& vn) {
3753 NEON2RegMisc(vd, vn, NEON_USQADD);
3754 }
3755
3756 void Assembler::abs(const VRegister& vd, const VRegister& vn) {
3757 DCHECK(vd.IsVector() || vd.Is1D());
3758 NEON2RegMisc(vd, vn, NEON_ABS);
3759 }
3760
3761 void Assembler::sqabs(const VRegister& vd, const VRegister& vn) {
3762 NEON2RegMisc(vd, vn, NEON_SQABS);
3763 }
3764
3765 void Assembler::neg(const VRegister& vd, const VRegister& vn) {
3766 DCHECK(vd.IsVector() || vd.Is1D());
3767 NEON2RegMisc(vd, vn, NEON_NEG);
3768 }
3769
3770 void Assembler::sqneg(const VRegister& vd, const VRegister& vn) {
3771 NEON2RegMisc(vd, vn, NEON_SQNEG);
3772 }
3773
3774 void Assembler::NEONXtn(const VRegister& vd, const VRegister& vn,
3775 NEON2RegMiscOp vop) {
3776 Instr format, op = vop;
3777 if (vd.IsScalar()) {
3778 DCHECK((vd.Is1B() && vn.Is1H()) || (vd.Is1H() && vn.Is1S()) ||
3779 (vd.Is1S() && vn.Is1D()));
3780 op |= NEON_Q | NEONScalar;
3781 format = SFormat(vd);
3782 } else {
3783 DCHECK((vd.Is8B() && vn.Is8H()) || (vd.Is4H() && vn.Is4S()) ||
3784 (vd.Is2S() && vn.Is2D()) || (vd.Is16B() && vn.Is8H()) ||
3785 (vd.Is8H() && vn.Is4S()) || (vd.Is4S() && vn.Is2D()));
3786 format = VFormat(vd);
3787 }
3788 Emit(format | op | Rn(vn) | Rd(vd));
3789 }
3790
3791 void Assembler::xtn(const VRegister& vd, const VRegister& vn) {
3792 DCHECK(vd.IsVector() && vd.IsD());
3793 NEONXtn(vd, vn, NEON_XTN);
3794 }
3795
3796 void Assembler::xtn2(const VRegister& vd, const VRegister& vn) {
3797 DCHECK(vd.IsVector() && vd.IsQ());
3798 NEONXtn(vd, vn, NEON_XTN);
3799 }
3800
3801 void Assembler::sqxtn(const VRegister& vd, const VRegister& vn) {
3802 DCHECK(vd.IsScalar() || vd.IsD());
3803 NEONXtn(vd, vn, NEON_SQXTN);
3804 }
3805
3806 void Assembler::sqxtn2(const VRegister& vd, const VRegister& vn) {
3807 DCHECK(vd.IsVector() && vd.IsQ());
3808 NEONXtn(vd, vn, NEON_SQXTN);
3809 }
3810
3811 void Assembler::sqxtun(const VRegister& vd, const VRegister& vn) {
3812 DCHECK(vd.IsScalar() || vd.IsD());
3813 NEONXtn(vd, vn, NEON_SQXTUN);
3814 }
3815
3816 void Assembler::sqxtun2(const VRegister& vd, const VRegister& vn) {
3817 DCHECK(vd.IsVector() && vd.IsQ());
3818 NEONXtn(vd, vn, NEON_SQXTUN);
3819 }
3820
3821 void Assembler::uqxtn(const VRegister& vd, const VRegister& vn) {
3822 DCHECK(vd.IsScalar() || vd.IsD());
3823 NEONXtn(vd, vn, NEON_UQXTN);
3824 }
3825
3826 void Assembler::uqxtn2(const VRegister& vd, const VRegister& vn) {
3827 DCHECK(vd.IsVector() && vd.IsQ());
3828 NEONXtn(vd, vn, NEON_UQXTN);
3829 }
3830
3831 // NEON NOT and RBIT are distinguised by bit 22, the bottom bit of "size".
3832 void Assembler::not_(const VRegister& vd, const VRegister& vn) {
3833 DCHECK(AreSameFormat(vd, vn));
3834 DCHECK(vd.Is8B() || vd.Is16B());
3835 Emit(VFormat(vd) | NEON_RBIT_NOT | Rn(vn) | Rd(vd));
3836 }
3837
3838 void Assembler::rbit(const VRegister& vd, const VRegister& vn) {
3839 DCHECK(AreSameFormat(vd, vn));
3840 DCHECK(vd.Is8B() || vd.Is16B());
3841 Emit(VFormat(vn) | (1 << NEONSize_offset) | NEON_RBIT_NOT | Rn(vn) | Rd(vd));
3842 }
3843
3844 void Assembler::ext(const VRegister& vd, const VRegister& vn,
3845 const VRegister& vm, int index) {
3846 DCHECK(AreSameFormat(vd, vn, vm));
3847 DCHECK(vd.Is8B() || vd.Is16B());
3848 DCHECK((0 <= index) && (index < vd.LaneCount()));
3849 Emit(VFormat(vd) | NEON_EXT | Rm(vm) | ImmNEONExt(index) | Rn(vn) | Rd(vd));
3850 }
3851
3852 void Assembler::dup(const VRegister& vd, const VRegister& vn, int vn_index) {
3853 Instr q, scalar;
3854
3855 // We support vn arguments of the form vn.VxT() or vn.T(), where x is the
3856 // number of lanes, and T is b, h, s or d.
3857 int lane_size = vn.LaneSizeInBytes();
3858 NEONFormatField format;
3859 switch (lane_size) {
3860 case 1:
3861 format = NEON_16B;
3862 break;
3863 case 2:
3864 format = NEON_8H;
3865 break;
3866 case 4:
3867 format = NEON_4S;
3868 break;
3869 default:
3870 DCHECK_EQ(lane_size, 8);
3871 format = NEON_2D;
3872 break;
3873 }
3874
3875 if (vd.IsScalar()) {
3876 q = NEON_Q;
3877 scalar = NEONScalar;
3878 } else {
3879 DCHECK(!vd.Is1D());
3880 q = vd.IsD() ? 0 : NEON_Q;
3881 scalar = 0;
3882 }
3883 Emit(q | scalar | NEON_DUP_ELEMENT | ImmNEON5(format, vn_index) | Rn(vn) |
3884 Rd(vd));
3885 }
2122 3886
2123 void Assembler::dcptr(Label* label) { 3887 void Assembler::dcptr(Label* label) {
2124 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE); 3888 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
2125 if (label->is_bound()) { 3889 if (label->is_bound()) {
2126 // The label is bound, so it does not need to be updated and the internal 3890 // The label is bound, so it does not need to be updated and the internal
2127 // reference should be emitted. 3891 // reference should be emitted.
2128 // 3892 //
2129 // In this case, label->pos() returns the offset of the label from the 3893 // In this case, label->pos() returns the offset of the label from the
2130 // start of the buffer. 3894 // start of the buffer.
2131 internal_reference_positions_.push_back(pc_offset()); 3895 internal_reference_positions_.push_back(pc_offset());
(...skipping 24 matching lines...) Expand all
2156 offset >>= kInstructionSizeLog2; 3920 offset >>= kInstructionSizeLog2;
2157 DCHECK(is_int32(offset)); 3921 DCHECK(is_int32(offset));
2158 uint32_t high16 = unsigned_bitextract_32(31, 16, offset); 3922 uint32_t high16 = unsigned_bitextract_32(31, 16, offset);
2159 uint32_t low16 = unsigned_bitextract_32(15, 0, offset); 3923 uint32_t low16 = unsigned_bitextract_32(15, 0, offset);
2160 3924
2161 brk(high16); 3925 brk(high16);
2162 brk(low16); 3926 brk(low16);
2163 } 3927 }
2164 } 3928 }
2165 3929
2166
2167 // Note:
2168 // Below, a difference in case for the same letter indicates a 3930 // Below, a difference in case for the same letter indicates a
2169 // negated bit. 3931 // negated bit. If b is 1, then B is 0.
2170 // If b is 1, then B is 0. 3932 uint32_t Assembler::FPToImm8(double imm) {
2171 Instr Assembler::ImmFP32(float imm) {
2172 DCHECK(IsImmFP32(imm));
2173 // bits: aBbb.bbbc.defg.h000.0000.0000.0000.0000
2174 uint32_t bits = float_to_rawbits(imm);
2175 // bit7: a000.0000
2176 uint32_t bit7 = ((bits >> 31) & 0x1) << 7;
2177 // bit6: 0b00.0000
2178 uint32_t bit6 = ((bits >> 29) & 0x1) << 6;
2179 // bit5_to_0: 00cd.efgh
2180 uint32_t bit5_to_0 = (bits >> 19) & 0x3f;
2181
2182 return (bit7 | bit6 | bit5_to_0) << ImmFP_offset;
2183 }
2184
2185
2186 Instr Assembler::ImmFP64(double imm) {
2187 DCHECK(IsImmFP64(imm)); 3933 DCHECK(IsImmFP64(imm));
2188 // bits: aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000 3934 // bits: aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000
2189 // 0000.0000.0000.0000.0000.0000.0000.0000 3935 // 0000.0000.0000.0000.0000.0000.0000.0000
2190 uint64_t bits = double_to_rawbits(imm); 3936 uint64_t bits = bit_cast<uint64_t>(imm);
2191 // bit7: a000.0000 3937 // bit7: a000.0000
2192 uint64_t bit7 = ((bits >> 63) & 0x1) << 7; 3938 uint64_t bit7 = ((bits >> 63) & 0x1) << 7;
2193 // bit6: 0b00.0000 3939 // bit6: 0b00.0000
2194 uint64_t bit6 = ((bits >> 61) & 0x1) << 6; 3940 uint64_t bit6 = ((bits >> 61) & 0x1) << 6;
2195 // bit5_to_0: 00cd.efgh 3941 // bit5_to_0: 00cd.efgh
2196 uint64_t bit5_to_0 = (bits >> 48) & 0x3f; 3942 uint64_t bit5_to_0 = (bits >> 48) & 0x3f;
2197 3943
2198 return static_cast<Instr>((bit7 | bit6 | bit5_to_0) << ImmFP_offset); 3944 return static_cast<uint32_t>(bit7 | bit6 | bit5_to_0);
2199 } 3945 }
2200 3946
3947 Instr Assembler::ImmFP(double imm) { return FPToImm8(imm) << ImmFP_offset; }
3948 Instr Assembler::ImmNEONFP(double imm) {
3949 return ImmNEONabcdefgh(FPToImm8(imm));
3950 }
2201 3951
2202 // Code generation helpers. 3952 // Code generation helpers.
2203 void Assembler::MoveWide(const Register& rd, 3953 void Assembler::MoveWide(const Register& rd, uint64_t imm, int shift,
2204 uint64_t imm,
2205 int shift,
2206 MoveWideImmediateOp mov_op) { 3954 MoveWideImmediateOp mov_op) {
2207 // Ignore the top 32 bits of an immediate if we're moving to a W register. 3955 // Ignore the top 32 bits of an immediate if we're moving to a W register.
2208 if (rd.Is32Bits()) { 3956 if (rd.Is32Bits()) {
2209 // Check that the top 32 bits are zero (a positive 32-bit number) or top 3957 // Check that the top 32 bits are zero (a positive 32-bit number) or top
2210 // 33 bits are one (a negative 32-bit number, sign extended to 64 bits). 3958 // 33 bits are one (a negative 32-bit number, sign extended to 64 bits).
2211 DCHECK(((imm >> kWRegSizeInBits) == 0) || 3959 DCHECK(((imm >> kWRegSizeInBits) == 0) ||
2212 ((imm >> (kWRegSizeInBits - 1)) == 0x1ffffffff)); 3960 ((imm >> (kWRegSizeInBits - 1)) == 0x1ffffffff));
2213 imm &= kWRegMask; 3961 imm &= kWRegMask;
2214 } 3962 }
2215 3963
(...skipping 21 matching lines...) Expand all
2237 shift = 3; 3985 shift = 3;
2238 } 3986 }
2239 } 3987 }
2240 3988
2241 DCHECK(is_uint16(imm)); 3989 DCHECK(is_uint16(imm));
2242 3990
2243 Emit(SF(rd) | MoveWideImmediateFixed | mov_op | Rd(rd) | 3991 Emit(SF(rd) | MoveWideImmediateFixed | mov_op | Rd(rd) |
2244 ImmMoveWide(static_cast<int>(imm)) | ShiftMoveWide(shift)); 3992 ImmMoveWide(static_cast<int>(imm)) | ShiftMoveWide(shift));
2245 } 3993 }
2246 3994
2247 3995 void Assembler::AddSub(const Register& rd, const Register& rn,
2248 void Assembler::AddSub(const Register& rd, 3996 const Operand& operand, FlagsUpdate S, AddSubOp op) {
2249 const Register& rn, 3997 DCHECK_EQ(rd.SizeInBits(), rn.SizeInBits());
2250 const Operand& operand,
2251 FlagsUpdate S,
2252 AddSubOp op) {
2253 DCHECK(rd.SizeInBits() == rn.SizeInBits());
2254 DCHECK(!operand.NeedsRelocation(this)); 3998 DCHECK(!operand.NeedsRelocation(this));
2255 if (operand.IsImmediate()) { 3999 if (operand.IsImmediate()) {
2256 int64_t immediate = operand.ImmediateValue(); 4000 int64_t immediate = operand.ImmediateValue();
2257 DCHECK(IsImmAddSub(immediate)); 4001 DCHECK(IsImmAddSub(immediate));
2258 Instr dest_reg = (S == SetFlags) ? Rd(rd) : RdSP(rd); 4002 Instr dest_reg = (S == SetFlags) ? Rd(rd) : RdSP(rd);
2259 Emit(SF(rd) | AddSubImmediateFixed | op | Flags(S) | 4003 Emit(SF(rd) | AddSubImmediateFixed | op | Flags(S) |
2260 ImmAddSub(static_cast<int>(immediate)) | dest_reg | RnSP(rn)); 4004 ImmAddSub(static_cast<int>(immediate)) | dest_reg | RnSP(rn));
2261 } else if (operand.IsShiftedRegister()) { 4005 } else if (operand.IsShiftedRegister()) {
2262 DCHECK(operand.reg().SizeInBits() == rd.SizeInBits()); 4006 DCHECK_EQ(operand.reg().SizeInBits(), rd.SizeInBits());
2263 DCHECK(operand.shift() != ROR); 4007 DCHECK_NE(operand.shift(), ROR);
2264 4008
2265 // For instructions of the form: 4009 // For instructions of the form:
2266 // add/sub wsp, <Wn>, <Wm> [, LSL #0-3 ] 4010 // add/sub wsp, <Wn>, <Wm> [, LSL #0-3 ]
2267 // add/sub <Wd>, wsp, <Wm> [, LSL #0-3 ] 4011 // add/sub <Wd>, wsp, <Wm> [, LSL #0-3 ]
2268 // add/sub wsp, wsp, <Wm> [, LSL #0-3 ] 4012 // add/sub wsp, wsp, <Wm> [, LSL #0-3 ]
2269 // adds/subs <Wd>, wsp, <Wm> [, LSL #0-3 ] 4013 // adds/subs <Wd>, wsp, <Wm> [, LSL #0-3 ]
2270 // or their 64-bit register equivalents, convert the operand from shifted to 4014 // or their 64-bit register equivalents, convert the operand from shifted to
2271 // extended register mode, and emit an add/sub extended instruction. 4015 // extended register mode, and emit an add/sub extended instruction.
2272 if (rn.IsSP() || rd.IsSP()) { 4016 if (rn.IsSP() || rd.IsSP()) {
2273 DCHECK(!(rd.IsSP() && (S == SetFlags))); 4017 DCHECK(!(rd.IsSP() && (S == SetFlags)));
2274 DataProcExtendedRegister(rd, rn, operand.ToExtendedRegister(), S, 4018 DataProcExtendedRegister(rd, rn, operand.ToExtendedRegister(), S,
2275 AddSubExtendedFixed | op); 4019 AddSubExtendedFixed | op);
2276 } else { 4020 } else {
2277 DataProcShiftedRegister(rd, rn, operand, S, AddSubShiftedFixed | op); 4021 DataProcShiftedRegister(rd, rn, operand, S, AddSubShiftedFixed | op);
2278 } 4022 }
2279 } else { 4023 } else {
2280 DCHECK(operand.IsExtendedRegister()); 4024 DCHECK(operand.IsExtendedRegister());
2281 DataProcExtendedRegister(rd, rn, operand, S, AddSubExtendedFixed | op); 4025 DataProcExtendedRegister(rd, rn, operand, S, AddSubExtendedFixed | op);
2282 } 4026 }
2283 } 4027 }
2284 4028
2285 4029 void Assembler::AddSubWithCarry(const Register& rd, const Register& rn,
2286 void Assembler::AddSubWithCarry(const Register& rd, 4030 const Operand& operand, FlagsUpdate S,
2287 const Register& rn,
2288 const Operand& operand,
2289 FlagsUpdate S,
2290 AddSubWithCarryOp op) { 4031 AddSubWithCarryOp op) {
2291 DCHECK(rd.SizeInBits() == rn.SizeInBits()); 4032 DCHECK_EQ(rd.SizeInBits(), rn.SizeInBits());
2292 DCHECK(rd.SizeInBits() == operand.reg().SizeInBits()); 4033 DCHECK_EQ(rd.SizeInBits(), operand.reg().SizeInBits());
2293 DCHECK(operand.IsShiftedRegister() && (operand.shift_amount() == 0)); 4034 DCHECK(operand.IsShiftedRegister() && (operand.shift_amount() == 0));
2294 DCHECK(!operand.NeedsRelocation(this)); 4035 DCHECK(!operand.NeedsRelocation(this));
2295 Emit(SF(rd) | op | Flags(S) | Rm(operand.reg()) | Rn(rn) | Rd(rd)); 4036 Emit(SF(rd) | op | Flags(S) | Rm(operand.reg()) | Rn(rn) | Rd(rd));
2296 } 4037 }
2297 4038
2298
2299 void Assembler::hlt(int code) { 4039 void Assembler::hlt(int code) {
2300 DCHECK(is_uint16(code)); 4040 DCHECK(is_uint16(code));
2301 Emit(HLT | ImmException(code)); 4041 Emit(HLT | ImmException(code));
2302 } 4042 }
2303 4043
2304
2305 void Assembler::brk(int code) { 4044 void Assembler::brk(int code) {
2306 DCHECK(is_uint16(code)); 4045 DCHECK(is_uint16(code));
2307 Emit(BRK | ImmException(code)); 4046 Emit(BRK | ImmException(code));
2308 } 4047 }
2309 4048
2310
2311 void Assembler::EmitStringData(const char* string) { 4049 void Assembler::EmitStringData(const char* string) {
2312 size_t len = strlen(string) + 1; 4050 size_t len = strlen(string) + 1;
2313 DCHECK(RoundUp(len, kInstructionSize) <= static_cast<size_t>(kGap)); 4051 DCHECK_LE(RoundUp(len, kInstructionSize), static_cast<size_t>(kGap));
2314 EmitData(string, static_cast<int>(len)); 4052 EmitData(string, static_cast<int>(len));
2315 // Pad with NULL characters until pc_ is aligned. 4053 // Pad with NULL characters until pc_ is aligned.
2316 const char pad[] = {'\0', '\0', '\0', '\0'}; 4054 const char pad[] = {'\0', '\0', '\0', '\0'};
2317 STATIC_ASSERT(sizeof(pad) == kInstructionSize); 4055 static_assert(sizeof(pad) == kInstructionSize,
4056 "Size of padding must match instruction size.");
2318 EmitData(pad, RoundUp(pc_offset(), kInstructionSize) - pc_offset()); 4057 EmitData(pad, RoundUp(pc_offset(), kInstructionSize) - pc_offset());
2319 } 4058 }
2320 4059
2321 4060
2322 void Assembler::debug(const char* message, uint32_t code, Instr params) { 4061 void Assembler::debug(const char* message, uint32_t code, Instr params) {
2323 #ifdef USE_SIMULATOR 4062 #ifdef USE_SIMULATOR
2324 // Don't generate simulator specific code if we are building a snapshot, which 4063 // Don't generate simulator specific code if we are building a snapshot, which
2325 // might be run on real hardware. 4064 // might be run on real hardware.
2326 if (!serializer_enabled()) { 4065 if (!serializer_enabled()) {
2327 // The arguments to the debug marker need to be contiguous in memory, so 4066 // The arguments to the debug marker need to be contiguous in memory, so
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
2424 } 4163 }
2425 4164
2426 4165
2427 void Assembler::DataProcessing1Source(const Register& rd, 4166 void Assembler::DataProcessing1Source(const Register& rd,
2428 const Register& rn, 4167 const Register& rn,
2429 DataProcessing1SourceOp op) { 4168 DataProcessing1SourceOp op) {
2430 DCHECK(rd.SizeInBits() == rn.SizeInBits()); 4169 DCHECK(rd.SizeInBits() == rn.SizeInBits());
2431 Emit(SF(rn) | op | Rn(rn) | Rd(rd)); 4170 Emit(SF(rn) | op | Rn(rn) | Rd(rd));
2432 } 4171 }
2433 4172
2434 4173 void Assembler::FPDataProcessing1Source(const VRegister& vd,
2435 void Assembler::FPDataProcessing1Source(const FPRegister& fd, 4174 const VRegister& vn,
2436 const FPRegister& fn,
2437 FPDataProcessing1SourceOp op) { 4175 FPDataProcessing1SourceOp op) {
2438 Emit(FPType(fn) | op | Rn(fn) | Rd(fd)); 4176 Emit(FPType(vn) | op | Rn(vn) | Rd(vd));
2439 } 4177 }
2440 4178
2441 4179 void Assembler::FPDataProcessing2Source(const VRegister& fd,
2442 void Assembler::FPDataProcessing2Source(const FPRegister& fd, 4180 const VRegister& fn,
2443 const FPRegister& fn, 4181 const VRegister& fm,
2444 const FPRegister& fm,
2445 FPDataProcessing2SourceOp op) { 4182 FPDataProcessing2SourceOp op) {
2446 DCHECK(fd.SizeInBits() == fn.SizeInBits()); 4183 DCHECK(fd.SizeInBits() == fn.SizeInBits());
2447 DCHECK(fd.SizeInBits() == fm.SizeInBits()); 4184 DCHECK(fd.SizeInBits() == fm.SizeInBits());
2448 Emit(FPType(fd) | op | Rm(fm) | Rn(fn) | Rd(fd)); 4185 Emit(FPType(fd) | op | Rm(fm) | Rn(fn) | Rd(fd));
2449 } 4186 }
2450 4187
2451 4188 void Assembler::FPDataProcessing3Source(const VRegister& fd,
2452 void Assembler::FPDataProcessing3Source(const FPRegister& fd, 4189 const VRegister& fn,
2453 const FPRegister& fn, 4190 const VRegister& fm,
2454 const FPRegister& fm, 4191 const VRegister& fa,
2455 const FPRegister& fa,
2456 FPDataProcessing3SourceOp op) { 4192 FPDataProcessing3SourceOp op) {
2457 DCHECK(AreSameSizeAndType(fd, fn, fm, fa)); 4193 DCHECK(AreSameSizeAndType(fd, fn, fm, fa));
2458 Emit(FPType(fd) | op | Rm(fm) | Rn(fn) | Rd(fd) | Ra(fa)); 4194 Emit(FPType(fd) | op | Rm(fm) | Rn(fn) | Rd(fd) | Ra(fa));
2459 } 4195 }
2460 4196
4197 void Assembler::NEONModifiedImmShiftLsl(const VRegister& vd, const int imm8,
4198 const int left_shift,
4199 NEONModifiedImmediateOp op) {
4200 DCHECK(vd.Is8B() || vd.Is16B() || vd.Is4H() || vd.Is8H() || vd.Is2S() ||
4201 vd.Is4S());
4202 DCHECK((left_shift == 0) || (left_shift == 8) || (left_shift == 16) ||
4203 (left_shift == 24));
4204 DCHECK(is_uint8(imm8));
4205
4206 int cmode_1, cmode_2, cmode_3;
4207 if (vd.Is8B() || vd.Is16B()) {
4208 DCHECK_EQ(op, NEONModifiedImmediate_MOVI);
4209 cmode_1 = 1;
4210 cmode_2 = 1;
4211 cmode_3 = 1;
4212 } else {
4213 cmode_1 = (left_shift >> 3) & 1;
4214 cmode_2 = left_shift >> 4;
4215 cmode_3 = 0;
4216 if (vd.Is4H() || vd.Is8H()) {
4217 DCHECK((left_shift == 0) || (left_shift == 8));
4218 cmode_3 = 1;
4219 }
4220 }
4221 int cmode = (cmode_3 << 3) | (cmode_2 << 2) | (cmode_1 << 1);
4222
4223 Instr q = vd.IsQ() ? NEON_Q : 0;
4224
4225 Emit(q | op | ImmNEONabcdefgh(imm8) | NEONCmode(cmode) | Rd(vd));
4226 }
4227
4228 void Assembler::NEONModifiedImmShiftMsl(const VRegister& vd, const int imm8,
4229 const int shift_amount,
4230 NEONModifiedImmediateOp op) {
4231 DCHECK(vd.Is2S() || vd.Is4S());
4232 DCHECK((shift_amount == 8) || (shift_amount == 16));
4233 DCHECK(is_uint8(imm8));
4234
4235 int cmode_0 = (shift_amount >> 4) & 1;
4236 int cmode = 0xc | cmode_0;
4237
4238 Instr q = vd.IsQ() ? NEON_Q : 0;
4239
4240 Emit(q | op | ImmNEONabcdefgh(imm8) | NEONCmode(cmode) | Rd(vd));
4241 }
2461 4242
2462 void Assembler::EmitShift(const Register& rd, 4243 void Assembler::EmitShift(const Register& rd,
2463 const Register& rn, 4244 const Register& rn,
2464 Shift shift, 4245 Shift shift,
2465 unsigned shift_amount) { 4246 unsigned shift_amount) {
2466 switch (shift) { 4247 switch (shift) {
2467 case LSL: 4248 case LSL:
2468 lsl(rd, rn, shift_amount); 4249 lsl(rd, rn, shift_amount);
2469 break; 4250 break;
2470 case LSR: 4251 case LSR:
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
2550 return is_uint12(immediate) || 4331 return is_uint12(immediate) ||
2551 (is_uint12(immediate >> 12) && ((immediate & 0xfff) == 0)); 4332 (is_uint12(immediate >> 12) && ((immediate & 0xfff) == 0));
2552 } 4333 }
2553 4334
2554 void Assembler::LoadStore(const CPURegister& rt, 4335 void Assembler::LoadStore(const CPURegister& rt,
2555 const MemOperand& addr, 4336 const MemOperand& addr,
2556 LoadStoreOp op) { 4337 LoadStoreOp op) {
2557 Instr memop = op | Rt(rt) | RnSP(addr.base()); 4338 Instr memop = op | Rt(rt) | RnSP(addr.base());
2558 4339
2559 if (addr.IsImmediateOffset()) { 4340 if (addr.IsImmediateOffset()) {
2560 LSDataSize size = CalcLSDataSize(op); 4341 unsigned size = CalcLSDataSize(op);
2561 if (IsImmLSScaled(addr.offset(), size)) { 4342 if (IsImmLSScaled(addr.offset(), size)) {
2562 int offset = static_cast<int>(addr.offset()); 4343 int offset = static_cast<int>(addr.offset());
2563 // Use the scaled addressing mode. 4344 // Use the scaled addressing mode.
2564 Emit(LoadStoreUnsignedOffsetFixed | memop | 4345 Emit(LoadStoreUnsignedOffsetFixed | memop |
2565 ImmLSUnsigned(offset >> size)); 4346 ImmLSUnsigned(offset >> size));
2566 } else if (IsImmLSUnscaled(addr.offset())) { 4347 } else if (IsImmLSUnscaled(addr.offset())) {
2567 int offset = static_cast<int>(addr.offset()); 4348 int offset = static_cast<int>(addr.offset());
2568 // Use the unscaled addressing mode. 4349 // Use the unscaled addressing mode.
2569 Emit(LoadStoreUnscaledOffsetFixed | memop | ImmLS(offset)); 4350 Emit(LoadStoreUnscaledOffsetFixed | memop | ImmLS(offset));
2570 } else { 4351 } else {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
2603 UNREACHABLE(); 4384 UNREACHABLE();
2604 } 4385 }
2605 } 4386 }
2606 } 4387 }
2607 4388
2608 4389
2609 bool Assembler::IsImmLSUnscaled(int64_t offset) { 4390 bool Assembler::IsImmLSUnscaled(int64_t offset) {
2610 return is_int9(offset); 4391 return is_int9(offset);
2611 } 4392 }
2612 4393
2613 4394 bool Assembler::IsImmLSScaled(int64_t offset, unsigned size) {
2614 bool Assembler::IsImmLSScaled(int64_t offset, LSDataSize size) {
2615 bool offset_is_size_multiple = (((offset >> size) << size) == offset); 4395 bool offset_is_size_multiple = (((offset >> size) << size) == offset);
2616 return offset_is_size_multiple && is_uint12(offset >> size); 4396 return offset_is_size_multiple && is_uint12(offset >> size);
2617 } 4397 }
2618 4398
2619 4399 bool Assembler::IsImmLSPair(int64_t offset, unsigned size) {
2620 bool Assembler::IsImmLSPair(int64_t offset, LSDataSize size) {
2621 bool offset_is_size_multiple = (((offset >> size) << size) == offset); 4400 bool offset_is_size_multiple = (((offset >> size) << size) == offset);
2622 return offset_is_size_multiple && is_int7(offset >> size); 4401 return offset_is_size_multiple && is_int7(offset >> size);
2623 } 4402 }
2624 4403
2625 4404
2626 bool Assembler::IsImmLLiteral(int64_t offset) { 4405 bool Assembler::IsImmLLiteral(int64_t offset) {
2627 int inst_size = static_cast<int>(kInstructionSizeLog2); 4406 int inst_size = static_cast<int>(kInstructionSizeLog2);
2628 bool offset_is_inst_multiple = 4407 bool offset_is_inst_multiple =
2629 (((offset >> inst_size) << inst_size) == offset); 4408 (((offset >> inst_size) << inst_size) == offset);
2630 return offset_is_inst_multiple && is_intn(offset, ImmLLiteral_width); 4409 return offset_is_inst_multiple && is_intn(offset, ImmLLiteral_width);
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
2841 4620
2842 4621
2843 bool Assembler::IsImmConditionalCompare(int64_t immediate) { 4622 bool Assembler::IsImmConditionalCompare(int64_t immediate) {
2844 return is_uint5(immediate); 4623 return is_uint5(immediate);
2845 } 4624 }
2846 4625
2847 4626
2848 bool Assembler::IsImmFP32(float imm) { 4627 bool Assembler::IsImmFP32(float imm) {
2849 // Valid values will have the form: 4628 // Valid values will have the form:
2850 // aBbb.bbbc.defg.h000.0000.0000.0000.0000 4629 // aBbb.bbbc.defg.h000.0000.0000.0000.0000
2851 uint32_t bits = float_to_rawbits(imm); 4630 uint32_t bits = bit_cast<uint32_t>(imm);
2852 // bits[19..0] are cleared. 4631 // bits[19..0] are cleared.
2853 if ((bits & 0x7ffff) != 0) { 4632 if ((bits & 0x7ffff) != 0) {
2854 return false; 4633 return false;
2855 } 4634 }
2856 4635
2857 // bits[29..25] are all set or all cleared. 4636 // bits[29..25] are all set or all cleared.
2858 uint32_t b_pattern = (bits >> 16) & 0x3e00; 4637 uint32_t b_pattern = (bits >> 16) & 0x3e00;
2859 if (b_pattern != 0 && b_pattern != 0x3e00) { 4638 if (b_pattern != 0 && b_pattern != 0x3e00) {
2860 return false; 4639 return false;
2861 } 4640 }
2862 4641
2863 // bit[30] and bit[29] are opposite. 4642 // bit[30] and bit[29] are opposite.
2864 if (((bits ^ (bits << 1)) & 0x40000000) == 0) { 4643 if (((bits ^ (bits << 1)) & 0x40000000) == 0) {
2865 return false; 4644 return false;
2866 } 4645 }
2867 4646
2868 return true; 4647 return true;
2869 } 4648 }
2870 4649
2871 4650
2872 bool Assembler::IsImmFP64(double imm) { 4651 bool Assembler::IsImmFP64(double imm) {
2873 // Valid values will have the form: 4652 // Valid values will have the form:
2874 // aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000 4653 // aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000
2875 // 0000.0000.0000.0000.0000.0000.0000.0000 4654 // 0000.0000.0000.0000.0000.0000.0000.0000
2876 uint64_t bits = double_to_rawbits(imm); 4655 uint64_t bits = bit_cast<uint64_t>(imm);
2877 // bits[47..0] are cleared. 4656 // bits[47..0] are cleared.
2878 if ((bits & 0xffffffffffffL) != 0) { 4657 if ((bits & 0xffffffffffffL) != 0) {
2879 return false; 4658 return false;
2880 } 4659 }
2881 4660
2882 // bits[61..54] are all set or all cleared. 4661 // bits[61..54] are all set or all cleared.
2883 uint32_t b_pattern = (bits >> 48) & 0x3fc0; 4662 uint32_t b_pattern = (bits >> 48) & 0x3fc0;
2884 if (b_pattern != 0 && b_pattern != 0x3fc0) { 4663 if (b_pattern != 0 && b_pattern != 0x3fc0) {
2885 return false; 4664 return false;
2886 } 4665 }
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after
3224 movk(scratch, (target_offset >> 32) & 0xFFFF, 32); 5003 movk(scratch, (target_offset >> 32) & 0xFFFF, 32);
3225 DCHECK((target_offset >> 48) == 0); 5004 DCHECK((target_offset >> 48) == 0);
3226 add(rd, rd, scratch); 5005 add(rd, rd, scratch);
3227 } 5006 }
3228 5007
3229 5008
3230 } // namespace internal 5009 } // namespace internal
3231 } // namespace v8 5010 } // namespace v8
3232 5011
3233 #endif // V8_TARGET_ARCH_ARM64 5012 #endif // V8_TARGET_ARCH_ARM64
OLDNEW
« no previous file with comments | « src/arm64/assembler-arm64.h ('k') | src/arm64/assembler-arm64-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698