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

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

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

Powered by Google App Engine
This is Rietveld 408576698