Changeset 278856 in webkit
- Timestamp:
- Jun 14, 2021, 6:04:01 PM (4 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
TabularUnified trunk/Source/JavaScriptCore/ChangeLog ¶
r278846 r278856 1 2021-06-14 Mark Lam <mark.lam@apple.com> 2 3 Add ldp and stp support for FP registers, plus some bug fixes. 4 https://bugs.webkit.org/show_bug.cgi?id=226998 5 rdar://79313717 6 7 Reviewed by Robin Morisset. 8 9 This patch does the following: 10 1. Add ldp and stp support for FP registers. 11 This simply entails providing wrappers that take FPRegisterID and passing true 12 for the V bit to the underlying loadStoreRegisterPairXXX encoding function. 13 V is for vector (aka floating point). This will cause bit 26 in the instruction 14 to be set indicating that it's loading / storing floating point registers. 15 16 2. Add ARM64 disassembler support ldp and stp for FP registers. 17 This includes fixing A64DOpcodeLoadStoreRegisterPair::mask to not exclude the 18 FP versions of the instructions. 19 20 3. Add ARM64Assembler query methods for determining if an immediate is encodable 21 as the signed 12 bit immediate of ldp and stp instructions. 22 23 4. Fix ldp and stp offset form to take an int instead of an unsigned. The 24 immediate it takes is a 12-bit signed int, not unsigned. 25 26 5. In loadStoreRegisterPairXXX encoding functions used by the forms of ldp and stp, 27 RELEASE_ASSERT that the passed in immediate is encodable. Unlike ldur / stur, 28 there is no form of ldp / stp that takes the offset in a register that can be 29 used as a fail over. Hence, if the immediate is not encodable, this is a 30 non-recoverable event. The client is responsible for ensuring that the offset 31 is encodable. 32 33 6. Added some testmasm tests for testing the offset form (as opposed to PreIndex 34 and PostIndex forms) of ldp and stp. We currently only use the offset form 35 in our JITs. 36 37 * assembler/ARM64Assembler.h: 38 (JSC::ARM64Assembler::isValidLDPImm): 39 (JSC::ARM64Assembler::isValidLDPFPImm): 40 (JSC::ARM64Assembler::ldp): 41 (JSC::ARM64Assembler::ldnp): 42 (JSC::ARM64Assembler::isValidSTPImm): 43 (JSC::ARM64Assembler::isValidSTPFPImm): 44 (JSC::ARM64Assembler::stp): 45 (JSC::ARM64Assembler::stnp): 46 (JSC::ARM64Assembler::loadStoreRegisterPairPostIndex): 47 (JSC::ARM64Assembler::loadStoreRegisterPairPreIndex): 48 (JSC::ARM64Assembler::loadStoreRegisterPairOffset): 49 (JSC::ARM64Assembler::loadStoreRegisterPairNonTemporal): 50 * assembler/AssemblerCommon.h: 51 (JSC::isValidSignedImm7): 52 * assembler/MacroAssemblerARM64.h: 53 (JSC::MacroAssemblerARM64::loadPair64): 54 (JSC::MacroAssemblerARM64::storePair64): 55 * assembler/testmasm.cpp: 56 (JSC::testLoadStorePair64Int64): 57 (JSC::testLoadStorePair64Double): 58 * disassembler/ARM64/A64DOpcode.cpp: 59 (JSC::ARM64Disassembler::A64DOpcodeLoadStoreRegisterPair::format): 60 * disassembler/ARM64/A64DOpcode.h: 61 1 62 2021-06-14 Yijia Huang <yijia_huang@apple.com> 2 63 -
TabularUnified trunk/Source/JavaScriptCore/assembler/ARM64Assembler.h ¶
r275285 r278856 1 1 /* 2 * Copyright (C) 2012-202 0Apple Inc. All rights reserved.2 * Copyright (C) 2012-2021 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 1116 1116 1117 1117 template<int datasize> 1118 ALWAYS_INLINE static bool isValidLDPImm(int immediate) 1119 { 1120 unsigned immedShiftAmount = memPairOffsetShift(false, MEMPAIROPSIZE_INT(datasize)); 1121 return isValidSignedImm7(immediate, immedShiftAmount); 1122 } 1123 1124 template<int datasize> 1125 ALWAYS_INLINE static bool isValidLDPFPImm(int immediate) 1126 { 1127 unsigned immedShiftAmount = memPairOffsetShift(true, MEMPAIROPSIZE_FP(datasize)); 1128 return isValidSignedImm7(immediate, immedShiftAmount); 1129 } 1130 1131 template<int datasize> 1118 1132 ALWAYS_INLINE void ldp(RegisterID rt, RegisterID rt2, RegisterID rn, PairPostIndex simm) 1119 1133 { … … 1130 1144 1131 1145 template<int datasize> 1132 ALWAYS_INLINE void ldp(RegisterID rt, RegisterID rt2, RegisterID rn, unsigned pimm = 0) 1133 { 1134 CHECK_DATASIZE(); 1135 insn(loadStoreRegisterPairOffset(MEMPAIROPSIZE_INT(datasize), false, MemOp_LOAD, pimm, rn, rt, rt2)); 1136 } 1137 1138 template<int datasize> 1139 ALWAYS_INLINE void ldnp(RegisterID rt, RegisterID rt2, RegisterID rn, unsigned pimm = 0) 1140 { 1141 CHECK_DATASIZE(); 1142 insn(loadStoreRegisterPairNonTemporal(MEMPAIROPSIZE_INT(datasize), false, MemOp_LOAD, pimm, rn, rt, rt2)); 1146 ALWAYS_INLINE void ldp(RegisterID rt, RegisterID rt2, RegisterID rn, int simm = 0) 1147 { 1148 CHECK_DATASIZE(); 1149 insn(loadStoreRegisterPairOffset(MEMPAIROPSIZE_INT(datasize), false, MemOp_LOAD, simm, rn, rt, rt2)); 1150 } 1151 1152 template<int datasize> 1153 ALWAYS_INLINE void ldnp(RegisterID rt, RegisterID rt2, RegisterID rn, int simm = 0) 1154 { 1155 CHECK_DATASIZE(); 1156 insn(loadStoreRegisterPairNonTemporal(MEMPAIROPSIZE_INT(datasize), false, MemOp_LOAD, simm, rn, rt, rt2)); 1157 } 1158 1159 template<int datasize> 1160 ALWAYS_INLINE void ldp(FPRegisterID rt, FPRegisterID rt2, RegisterID rn, PairPostIndex simm) 1161 { 1162 CHECK_DATASIZE(); 1163 insn(loadStoreRegisterPairPostIndex(MEMPAIROPSIZE_FP(datasize), true, MemOp_LOAD, simm, rn, rt, rt2)); 1164 } 1165 1166 template<int datasize> 1167 ALWAYS_INLINE void ldp(FPRegisterID rt, FPRegisterID rt2, RegisterID rn, PairPreIndex simm) 1168 { 1169 CHECK_DATASIZE(); 1170 insn(loadStoreRegisterPairPreIndex(MEMPAIROPSIZE_FP(datasize), true, MemOp_LOAD, simm, rn, rt, rt2)); 1171 } 1172 1173 template<int datasize> 1174 ALWAYS_INLINE void ldp(FPRegisterID rt, FPRegisterID rt2, RegisterID rn, int simm = 0) 1175 { 1176 CHECK_DATASIZE(); 1177 insn(loadStoreRegisterPairOffset(MEMPAIROPSIZE_FP(datasize), true, MemOp_LOAD, simm, rn, rt, rt2)); 1178 } 1179 1180 template<int datasize> 1181 ALWAYS_INLINE void ldnp(FPRegisterID rt, FPRegisterID rt2, RegisterID rn, int simm = 0) 1182 { 1183 CHECK_DATASIZE(); 1184 insn(loadStoreRegisterPairNonTemporal(MEMPAIROPSIZE_FP(datasize), true, MemOp_LOAD, simm, rn, rt, rt2)); 1143 1185 } 1144 1186 … … 1745 1787 1746 1788 template<int datasize> 1789 ALWAYS_INLINE static bool isValidSTPImm(int immediate) 1790 { 1791 return isValidLDPImm<datasize>(immediate); 1792 } 1793 1794 template<int datasize> 1795 ALWAYS_INLINE static bool isValidSTPFPImm(int immediate) 1796 { 1797 return isValidLDPFPImm<datasize>(immediate); 1798 } 1799 1800 template<int datasize> 1747 1801 ALWAYS_INLINE void stp(RegisterID rt, RegisterID rt2, RegisterID rn, PairPostIndex simm) 1748 1802 { … … 1759 1813 1760 1814 template<int datasize> 1761 ALWAYS_INLINE void stp(RegisterID rt, RegisterID rt2, RegisterID rn, unsigned pimm = 0) 1762 { 1763 CHECK_DATASIZE(); 1764 insn(loadStoreRegisterPairOffset(MEMPAIROPSIZE_INT(datasize), false, MemOp_STORE, pimm, rn, rt, rt2)); 1765 } 1766 1767 template<int datasize> 1768 ALWAYS_INLINE void stnp(RegisterID rt, RegisterID rt2, RegisterID rn, unsigned pimm = 0) 1769 { 1770 CHECK_DATASIZE(); 1771 insn(loadStoreRegisterPairNonTemporal(MEMPAIROPSIZE_INT(datasize), false, MemOp_STORE, pimm, rn, rt, rt2)); 1815 ALWAYS_INLINE void stp(RegisterID rt, RegisterID rt2, RegisterID rn, int simm = 0) 1816 { 1817 CHECK_DATASIZE(); 1818 insn(loadStoreRegisterPairOffset(MEMPAIROPSIZE_INT(datasize), false, MemOp_STORE, simm, rn, rt, rt2)); 1819 } 1820 1821 template<int datasize> 1822 ALWAYS_INLINE void stnp(RegisterID rt, RegisterID rt2, RegisterID rn, int simm = 0) 1823 { 1824 CHECK_DATASIZE(); 1825 insn(loadStoreRegisterPairNonTemporal(MEMPAIROPSIZE_INT(datasize), false, MemOp_STORE, simm, rn, rt, rt2)); 1826 } 1827 1828 template<int datasize> 1829 ALWAYS_INLINE void stp(FPRegisterID rt, FPRegisterID rt2, RegisterID rn, PairPostIndex simm) 1830 { 1831 CHECK_DATASIZE(); 1832 insn(loadStoreRegisterPairPostIndex(MEMPAIROPSIZE_FP(datasize), true, MemOp_STORE, simm, rn, rt, rt2)); 1833 } 1834 1835 template<int datasize> 1836 ALWAYS_INLINE void stp(FPRegisterID rt, FPRegisterID rt2, RegisterID rn, PairPreIndex simm) 1837 { 1838 CHECK_DATASIZE(); 1839 insn(loadStoreRegisterPairPreIndex(MEMPAIROPSIZE_FP(datasize), true, MemOp_STORE, simm, rn, rt, rt2)); 1840 } 1841 1842 template<int datasize> 1843 ALWAYS_INLINE void stp(FPRegisterID rt, FPRegisterID rt2, RegisterID rn, int simm = 0) 1844 { 1845 CHECK_DATASIZE(); 1846 insn(loadStoreRegisterPairOffset(MEMPAIROPSIZE_FP(datasize), true, MemOp_STORE, simm, rn, rt, rt2)); 1847 } 1848 1849 template<int datasize> 1850 ALWAYS_INLINE void stnp(FPRegisterID rt, FPRegisterID rt2, RegisterID rn, int simm = 0) 1851 { 1852 CHECK_DATASIZE(); 1853 insn(loadStoreRegisterPairNonTemporal(MEMPAIROPSIZE_FP(datasize), true, MemOp_STORE, simm, rn, rt, rt2)); 1772 1854 } 1773 1855 … … 3545 3627 ASSERT(V || (size != MemPairOp_LoadSigned_32) || (opc == MemOp_LOAD)); // There isn't an integer store signed. 3546 3628 unsigned immedShiftAmount = memPairOffsetShift(V, size); 3629 RELEASE_ASSERT(isValidSignedImm7(immediate, immedShiftAmount)); 3547 3630 int imm7 = immediate >> immedShiftAmount; 3548 3631 ASSERT((imm7 << immedShiftAmount) == immediate && isInt<7>(imm7)); … … 3576 3659 ASSERT(V || (size != MemPairOp_LoadSigned_32) || (opc == MemOp_LOAD)); // There isn't an integer store signed. 3577 3660 unsigned immedShiftAmount = memPairOffsetShift(V, size); 3661 RELEASE_ASSERT(isValidSignedImm7(immediate, immedShiftAmount)); 3578 3662 int imm7 = immediate >> immedShiftAmount; 3579 3663 ASSERT((imm7 << immedShiftAmount) == immediate && isInt<7>(imm7)); … … 3593 3677 ASSERT(V || (size != MemPairOp_LoadSigned_32) || (opc == MemOp_LOAD)); // There isn't an integer store signed. 3594 3678 unsigned immedShiftAmount = memPairOffsetShift(V, size); 3679 RELEASE_ASSERT(isValidSignedImm7(immediate, immedShiftAmount)); 3595 3680 int imm7 = immediate >> immedShiftAmount; 3596 3681 ASSERT((imm7 << immedShiftAmount) == immediate && isInt<7>(imm7)); … … 3610 3695 ASSERT(V || (size != MemPairOp_LoadSigned_32) || (opc == MemOp_LOAD)); // There isn't an integer store signed. 3611 3696 unsigned immedShiftAmount = memPairOffsetShift(V, size); 3697 RELEASE_ASSERT(isValidSignedImm7(immediate, immedShiftAmount)); 3612 3698 int imm7 = immediate >> immedShiftAmount; 3613 3699 ASSERT((imm7 << immedShiftAmount) == immediate && isInt<7>(imm7)); -
TabularUnified trunk/Source/JavaScriptCore/assembler/AssemblerCommon.h ¶
r254843 r278856 1 1 /* 2 * Copyright (C) 2012-20 19Apple Inc. All rights reserved.2 * Copyright (C) 2012-2021 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 75 75 } 76 76 77 ALWAYS_INLINE bool isValidSignedImm7(int32_t value, int alignmentShiftAmount) 78 { 79 constexpr int32_t disallowedHighBits = 32 - 7; 80 int32_t shiftedValue = value >> alignmentShiftAmount; 81 bool fitsIn7Bits = shiftedValue == ((shiftedValue << disallowedHighBits) >> disallowedHighBits); 82 bool hasCorrectAlignment = value == (shiftedValue << alignmentShiftAmount); 83 return fitsIn7Bits && hasCorrectAlignment; 84 } 85 77 86 class ARM64LogicalImmediate { 78 87 public: -
TabularUnified trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h ¶
r278846 r278856 1245 1245 } 1246 1246 1247 void loadPair64(RegisterID src, FPRegisterID dest1, FPRegisterID dest2) 1248 { 1249 loadPair64(src, TrustedImm32(0), dest1, dest2); 1250 } 1251 1252 void loadPair64(RegisterID src, TrustedImm32 offset, FPRegisterID dest1, FPRegisterID dest2) 1253 { 1254 m_assembler.ldp<64>(dest1, dest2, src, offset.m_value); 1255 } 1256 1247 1257 void abortWithReason(AbortReason reason) 1248 1258 { … … 1567 1577 { 1568 1578 m_assembler.stnp<64>(src1, src2, dest, offset.m_value); 1579 } 1580 1581 void storePair64(FPRegisterID src1, FPRegisterID src2, RegisterID dest) 1582 { 1583 storePair64(src1, src2, dest, TrustedImm32(0)); 1584 } 1585 1586 void storePair64(FPRegisterID src1, FPRegisterID src2, RegisterID dest, TrustedImm32 offset) 1587 { 1588 m_assembler.stp<64>(src1, src2, dest, offset.m_value); 1569 1589 } 1570 1590 -
TabularUnified trunk/Source/JavaScriptCore/assembler/testmasm.cpp ¶
r278846 r278856 1851 1851 #endif // CPU(X86_64) || CPU(ARM64) 1852 1852 1853 #if CPU(ARM64) 1854 void testLoadStorePair64Int64() 1855 { 1856 constexpr uint64_t initialValue = 0x5555aaaabbbb8800ull; 1857 constexpr uint64_t value1 = 42; 1858 constexpr uint64_t value2 = 0xcafebabe12345678ull; 1859 1860 uint64_t buffer[10]; 1861 1862 auto initBuffer = [&] { 1863 for (unsigned i = 0; i < 10; ++i) 1864 buffer[i] = initialValue + i; 1865 }; 1866 1867 struct Pair { 1868 uint64_t value1; 1869 uint64_t value2; 1870 }; 1871 1872 Pair pair; 1873 auto initPair = [&] { 1874 pair = { 0, 0 }; 1875 }; 1876 1877 // Test loadPair64. 1878 auto testLoadPair = [] (CCallHelpers& jit, int offset) { 1879 emitFunctionPrologue(jit); 1880 1881 constexpr GPRReg bufferGPR = GPRInfo::argumentGPR0; 1882 constexpr GPRReg pairGPR = GPRInfo::argumentGPR1; 1883 jit.loadPair64(bufferGPR, CCallHelpers::TrustedImm32(offset * sizeof(CPURegister)), GPRInfo::regT2, GPRInfo::regT3); 1884 1885 jit.store64(GPRInfo::regT2, CCallHelpers::Address(pairGPR, 0)); 1886 jit.store64(GPRInfo::regT3, CCallHelpers::Address(pairGPR, sizeof(uint64_t))); 1887 1888 emitFunctionEpilogue(jit); 1889 jit.ret(); 1890 }; 1891 1892 auto testLoadPair0 = compile([&] (CCallHelpers& jit) { 1893 testLoadPair(jit, 0); 1894 }); 1895 1896 initBuffer(); 1897 1898 initPair(); 1899 invoke<void>(testLoadPair0, &buffer[4], &pair); 1900 CHECK_EQ(pair.value1, initialValue + 4); 1901 CHECK_EQ(pair.value2, initialValue + 5); 1902 1903 initPair(); 1904 buffer[4] = value1; 1905 buffer[5] = value2; 1906 invoke<void>(testLoadPair0, &buffer[4], &pair); 1907 CHECK_EQ(pair.value1, value1); 1908 CHECK_EQ(pair.value2, value2); 1909 1910 auto testLoadPairMinus2 = compile([&] (CCallHelpers& jit) { 1911 testLoadPair(jit, -2); 1912 }); 1913 1914 initPair(); 1915 invoke<void>(testLoadPairMinus2, &buffer[4], &pair); 1916 CHECK_EQ(pair.value1, initialValue + 4 - 2); 1917 CHECK_EQ(pair.value2, initialValue + 5 - 2); 1918 1919 initPair(); 1920 buffer[4 - 2] = value2; 1921 buffer[5 - 2] = value1; 1922 invoke<void>(testLoadPairMinus2, &buffer[4], &pair); 1923 CHECK_EQ(pair.value1, value2); 1924 CHECK_EQ(pair.value2, value1); 1925 1926 auto testLoadPairPlus3 = compile([&] (CCallHelpers& jit) { 1927 testLoadPair(jit, 3); 1928 }); 1929 1930 initPair(); 1931 invoke<void>(testLoadPairPlus3, &buffer[4], &pair); 1932 CHECK_EQ(pair.value1, initialValue + 4 + 3); 1933 CHECK_EQ(pair.value2, initialValue + 5 + 3); 1934 1935 initPair(); 1936 buffer[4 + 3] = value1; 1937 buffer[5 + 3] = value2; 1938 invoke<void>(testLoadPairPlus3, &buffer[4], &pair); 1939 CHECK_EQ(pair.value1, value1); 1940 CHECK_EQ(pair.value2, value2); 1941 1942 // Test storePair64. 1943 auto testStorePair = [] (CCallHelpers& jit, int offset) { 1944 emitFunctionPrologue(jit); 1945 1946 constexpr GPRReg bufferGPR = GPRInfo::argumentGPR2; 1947 jit.storePair64(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1, bufferGPR, CCallHelpers::TrustedImm32(offset * sizeof(CPURegister))); 1948 1949 emitFunctionEpilogue(jit); 1950 jit.ret(); 1951 }; 1952 1953 auto testStorePair0 = compile([&] (CCallHelpers& jit) { 1954 testStorePair(jit, 0); 1955 }); 1956 1957 initBuffer(); 1958 invoke<void>(testStorePair0, value1, value2, &buffer[4]); 1959 CHECK_EQ(buffer[0], initialValue + 0); 1960 CHECK_EQ(buffer[1], initialValue + 1); 1961 CHECK_EQ(buffer[2], initialValue + 2); 1962 CHECK_EQ(buffer[3], initialValue + 3); 1963 CHECK_EQ(buffer[4], value1); 1964 CHECK_EQ(buffer[5], value2); 1965 CHECK_EQ(buffer[6], initialValue + 6); 1966 CHECK_EQ(buffer[7], initialValue + 7); 1967 CHECK_EQ(buffer[8], initialValue + 8); 1968 CHECK_EQ(buffer[9], initialValue + 9); 1969 1970 auto testStorePairMinus2 = compile([&] (CCallHelpers& jit) { 1971 testStorePair(jit, -2); 1972 }); 1973 1974 initBuffer(); 1975 invoke<void>(testStorePairMinus2, value1, value2, &buffer[4]); 1976 CHECK_EQ(buffer[0], initialValue + 0); 1977 CHECK_EQ(buffer[1], initialValue + 1); 1978 CHECK_EQ(buffer[2], value1); 1979 CHECK_EQ(buffer[3], value2); 1980 CHECK_EQ(buffer[4], initialValue + 4); 1981 CHECK_EQ(buffer[5], initialValue + 5); 1982 CHECK_EQ(buffer[6], initialValue + 6); 1983 CHECK_EQ(buffer[7], initialValue + 7); 1984 CHECK_EQ(buffer[8], initialValue + 8); 1985 CHECK_EQ(buffer[9], initialValue + 9); 1986 1987 auto testStorePairPlus3 = compile([&] (CCallHelpers& jit) { 1988 testStorePair(jit, 3); 1989 }); 1990 1991 initBuffer(); 1992 invoke<void>(testStorePairPlus3, value1, value2, &buffer[4]); 1993 CHECK_EQ(buffer[0], initialValue + 0); 1994 CHECK_EQ(buffer[1], initialValue + 1); 1995 CHECK_EQ(buffer[2], initialValue + 2); 1996 CHECK_EQ(buffer[3], initialValue + 3); 1997 CHECK_EQ(buffer[4], initialValue + 4); 1998 CHECK_EQ(buffer[5], initialValue + 5); 1999 CHECK_EQ(buffer[6], initialValue + 6); 2000 CHECK_EQ(buffer[7], value1); 2001 CHECK_EQ(buffer[8], value2); 2002 CHECK_EQ(buffer[9], initialValue + 9); 2003 2004 // Test storePair64 from 1 register. 2005 auto testStorePairFromOneReg = [] (CCallHelpers& jit, int offset) { 2006 emitFunctionPrologue(jit); 2007 2008 constexpr GPRReg bufferGPR = GPRInfo::argumentGPR1; 2009 jit.storePair64(GPRInfo::argumentGPR0, GPRInfo::argumentGPR0, bufferGPR, CCallHelpers::TrustedImm32(offset * sizeof(CPURegister))); 2010 2011 emitFunctionEpilogue(jit); 2012 jit.ret(); 2013 }; 2014 2015 auto testStorePairFromOneReg0 = compile([&] (CCallHelpers& jit) { 2016 testStorePairFromOneReg(jit, 0); 2017 }); 2018 2019 initBuffer(); 2020 invoke<void>(testStorePairFromOneReg0, value2, &buffer[4]); 2021 CHECK_EQ(buffer[0], initialValue + 0); 2022 CHECK_EQ(buffer[1], initialValue + 1); 2023 CHECK_EQ(buffer[2], initialValue + 2); 2024 CHECK_EQ(buffer[3], initialValue + 3); 2025 CHECK_EQ(buffer[4], value2); 2026 CHECK_EQ(buffer[5], value2); 2027 CHECK_EQ(buffer[6], initialValue + 6); 2028 CHECK_EQ(buffer[7], initialValue + 7); 2029 CHECK_EQ(buffer[8], initialValue + 8); 2030 CHECK_EQ(buffer[9], initialValue + 9); 2031 2032 auto testStorePairFromOneRegMinus2 = compile([&] (CCallHelpers& jit) { 2033 testStorePairFromOneReg(jit, -2); 2034 }); 2035 2036 initBuffer(); 2037 invoke<void>(testStorePairFromOneRegMinus2, value1, &buffer[4]); 2038 CHECK_EQ(buffer[0], initialValue + 0); 2039 CHECK_EQ(buffer[1], initialValue + 1); 2040 CHECK_EQ(buffer[2], value1); 2041 CHECK_EQ(buffer[3], value1); 2042 CHECK_EQ(buffer[4], initialValue + 4); 2043 CHECK_EQ(buffer[5], initialValue + 5); 2044 CHECK_EQ(buffer[6], initialValue + 6); 2045 CHECK_EQ(buffer[7], initialValue + 7); 2046 CHECK_EQ(buffer[8], initialValue + 8); 2047 CHECK_EQ(buffer[9], initialValue + 9); 2048 2049 auto testStorePairFromOneRegPlus3 = compile([&] (CCallHelpers& jit) { 2050 testStorePairFromOneReg(jit, 3); 2051 }); 2052 2053 initBuffer(); 2054 invoke<void>(testStorePairFromOneRegPlus3, value2, &buffer[4]); 2055 CHECK_EQ(buffer[0], initialValue + 0); 2056 CHECK_EQ(buffer[1], initialValue + 1); 2057 CHECK_EQ(buffer[2], initialValue + 2); 2058 CHECK_EQ(buffer[3], initialValue + 3); 2059 CHECK_EQ(buffer[4], initialValue + 4); 2060 CHECK_EQ(buffer[5], initialValue + 5); 2061 CHECK_EQ(buffer[6], initialValue + 6); 2062 CHECK_EQ(buffer[7], value2); 2063 CHECK_EQ(buffer[8], value2); 2064 CHECK_EQ(buffer[9], initialValue + 9); 2065 } 2066 2067 void testLoadStorePair64Double() 2068 { 2069 constexpr double initialValue = 10000.275; 2070 constexpr double value1 = 42.89; 2071 constexpr double value2 = -555.321; 2072 2073 double buffer[10]; 2074 2075 auto initBuffer = [&] { 2076 for (unsigned i = 0; i < 10; ++i) 2077 buffer[i] = initialValue + i; 2078 }; 2079 2080 struct Pair { 2081 double value1; 2082 double value2; 2083 }; 2084 2085 Pair pair; 2086 auto initPair = [&] { 2087 pair = { 0, 0 }; 2088 }; 2089 2090 // Test loadPair64. 2091 auto testLoadPair = [] (CCallHelpers& jit, int offset) { 2092 emitFunctionPrologue(jit); 2093 2094 constexpr GPRReg bufferGPR = GPRInfo::argumentGPR0; 2095 constexpr GPRReg pairGPR = GPRInfo::argumentGPR1; 2096 jit.loadPair64(bufferGPR, CCallHelpers::TrustedImm32(offset * sizeof(double)), FPRInfo::fpRegT0, FPRInfo::fpRegT1); 2097 2098 jit.storeDouble(FPRInfo::fpRegT0, CCallHelpers::Address(pairGPR, 0)); 2099 jit.storeDouble(FPRInfo::fpRegT1, CCallHelpers::Address(pairGPR, sizeof(uint64_t))); 2100 2101 emitFunctionEpilogue(jit); 2102 jit.ret(); 2103 }; 2104 2105 auto testLoadPair0 = compile([&] (CCallHelpers& jit) { 2106 testLoadPair(jit, 0); 2107 }); 2108 2109 initBuffer(); 2110 2111 initPair(); 2112 invoke<void>(testLoadPair0, &buffer[4], &pair); 2113 CHECK_EQ(pair.value1, initialValue + 4); 2114 CHECK_EQ(pair.value2, initialValue + 5); 2115 2116 initPair(); 2117 buffer[4] = value1; 2118 buffer[5] = value2; 2119 invoke<void>(testLoadPair0, &buffer[4], &pair); 2120 CHECK_EQ(pair.value1, value1); 2121 CHECK_EQ(pair.value2, value2); 2122 2123 auto testLoadPairMinus2 = compile([&] (CCallHelpers& jit) { 2124 testLoadPair(jit, -2); 2125 }); 2126 2127 initPair(); 2128 invoke<void>(testLoadPairMinus2, &buffer[4], &pair); 2129 CHECK_EQ(pair.value1, initialValue + 4 - 2); 2130 CHECK_EQ(pair.value2, initialValue + 5 - 2); 2131 2132 initPair(); 2133 buffer[4 - 2] = value2; 2134 buffer[5 - 2] = value1; 2135 invoke<void>(testLoadPairMinus2, &buffer[4], &pair); 2136 CHECK_EQ(pair.value1, value2); 2137 CHECK_EQ(pair.value2, value1); 2138 2139 auto testLoadPairPlus3 = compile([&] (CCallHelpers& jit) { 2140 testLoadPair(jit, 3); 2141 }); 2142 2143 initPair(); 2144 invoke<void>(testLoadPairPlus3, &buffer[4], &pair); 2145 CHECK_EQ(pair.value1, initialValue + 4 + 3); 2146 CHECK_EQ(pair.value2, initialValue + 5 + 3); 2147 2148 initPair(); 2149 buffer[4 + 3] = value1; 2150 buffer[5 + 3] = value2; 2151 invoke<void>(testLoadPairPlus3, &buffer[4], &pair); 2152 CHECK_EQ(pair.value1, value1); 2153 CHECK_EQ(pair.value2, value2); 2154 2155 // Test storePair64. 2156 auto testStorePair = [] (CCallHelpers& jit, int offset) { 2157 emitFunctionPrologue(jit); 2158 2159 constexpr GPRReg bufferGPR = GPRInfo::argumentGPR2; 2160 jit.move64ToDouble(GPRInfo::argumentGPR0, FPRInfo::fpRegT0); 2161 jit.move64ToDouble(GPRInfo::argumentGPR1, FPRInfo::fpRegT1); 2162 jit.storePair64(FPRInfo::fpRegT0, FPRInfo::fpRegT1, bufferGPR, CCallHelpers::TrustedImm32(offset * sizeof(double))); 2163 2164 emitFunctionEpilogue(jit); 2165 jit.ret(); 2166 }; 2167 2168 auto asInt64 = [] (double value) { 2169 return bitwise_cast<int64_t>(value); 2170 }; 2171 2172 auto testStorePair0 = compile([&] (CCallHelpers& jit) { 2173 testStorePair(jit, 0); 2174 }); 2175 2176 initBuffer(); 2177 invoke<void>(testStorePair0, asInt64(value1), asInt64(value2), &buffer[4]); 2178 CHECK_EQ(buffer[0], initialValue + 0); 2179 CHECK_EQ(buffer[1], initialValue + 1); 2180 CHECK_EQ(buffer[2], initialValue + 2); 2181 CHECK_EQ(buffer[3], initialValue + 3); 2182 CHECK_EQ(buffer[4], value1); 2183 CHECK_EQ(buffer[5], value2); 2184 CHECK_EQ(buffer[6], initialValue + 6); 2185 CHECK_EQ(buffer[7], initialValue + 7); 2186 CHECK_EQ(buffer[8], initialValue + 8); 2187 CHECK_EQ(buffer[9], initialValue + 9); 2188 2189 auto testStorePairMinus2 = compile([&] (CCallHelpers& jit) { 2190 testStorePair(jit, -2); 2191 }); 2192 2193 initBuffer(); 2194 invoke<void>(testStorePairMinus2, asInt64(value1), asInt64(value2), &buffer[4]); 2195 CHECK_EQ(buffer[0], initialValue + 0); 2196 CHECK_EQ(buffer[1], initialValue + 1); 2197 CHECK_EQ(buffer[2], value1); 2198 CHECK_EQ(buffer[3], value2); 2199 CHECK_EQ(buffer[4], initialValue + 4); 2200 CHECK_EQ(buffer[5], initialValue + 5); 2201 CHECK_EQ(buffer[6], initialValue + 6); 2202 CHECK_EQ(buffer[7], initialValue + 7); 2203 CHECK_EQ(buffer[8], initialValue + 8); 2204 CHECK_EQ(buffer[9], initialValue + 9); 2205 2206 auto testStorePairPlus3 = compile([&] (CCallHelpers& jit) { 2207 testStorePair(jit, 3); 2208 }); 2209 2210 initBuffer(); 2211 invoke<void>(testStorePairPlus3, asInt64(value1), asInt64(value2), &buffer[4]); 2212 CHECK_EQ(buffer[0], initialValue + 0); 2213 CHECK_EQ(buffer[1], initialValue + 1); 2214 CHECK_EQ(buffer[2], initialValue + 2); 2215 CHECK_EQ(buffer[3], initialValue + 3); 2216 CHECK_EQ(buffer[4], initialValue + 4); 2217 CHECK_EQ(buffer[5], initialValue + 5); 2218 CHECK_EQ(buffer[6], initialValue + 6); 2219 CHECK_EQ(buffer[7], value1); 2220 CHECK_EQ(buffer[8], value2); 2221 CHECK_EQ(buffer[9], initialValue + 9); 2222 2223 // Test storePair64 from 1 register. 2224 auto testStorePairFromOneReg = [] (CCallHelpers& jit, int offset) { 2225 emitFunctionPrologue(jit); 2226 2227 constexpr GPRReg bufferGPR = GPRInfo::argumentGPR1; 2228 jit.move64ToDouble(GPRInfo::argumentGPR0, FPRInfo::fpRegT0); 2229 jit.storePair64(FPRInfo::fpRegT0, FPRInfo::fpRegT0, bufferGPR, CCallHelpers::TrustedImm32(offset * sizeof(double))); 2230 2231 emitFunctionEpilogue(jit); 2232 jit.ret(); 2233 }; 2234 2235 auto testStorePairFromOneReg0 = compile([&] (CCallHelpers& jit) { 2236 testStorePairFromOneReg(jit, 0); 2237 }); 2238 2239 initBuffer(); 2240 invoke<void>(testStorePairFromOneReg0, asInt64(value2), &buffer[4]); 2241 CHECK_EQ(buffer[0], initialValue + 0); 2242 CHECK_EQ(buffer[1], initialValue + 1); 2243 CHECK_EQ(buffer[2], initialValue + 2); 2244 CHECK_EQ(buffer[3], initialValue + 3); 2245 CHECK_EQ(buffer[4], value2); 2246 CHECK_EQ(buffer[5], value2); 2247 CHECK_EQ(buffer[6], initialValue + 6); 2248 CHECK_EQ(buffer[7], initialValue + 7); 2249 CHECK_EQ(buffer[8], initialValue + 8); 2250 CHECK_EQ(buffer[9], initialValue + 9); 2251 2252 auto testStorePairFromOneRegMinus2 = compile([&] (CCallHelpers& jit) { 2253 testStorePairFromOneReg(jit, -2); 2254 }); 2255 2256 initBuffer(); 2257 invoke<void>(testStorePairFromOneRegMinus2, asInt64(value1), &buffer[4]); 2258 CHECK_EQ(buffer[0], initialValue + 0); 2259 CHECK_EQ(buffer[1], initialValue + 1); 2260 CHECK_EQ(buffer[2], value1); 2261 CHECK_EQ(buffer[3], value1); 2262 CHECK_EQ(buffer[4], initialValue + 4); 2263 CHECK_EQ(buffer[5], initialValue + 5); 2264 CHECK_EQ(buffer[6], initialValue + 6); 2265 CHECK_EQ(buffer[7], initialValue + 7); 2266 CHECK_EQ(buffer[8], initialValue + 8); 2267 CHECK_EQ(buffer[9], initialValue + 9); 2268 2269 auto testStorePairFromOneRegPlus3 = compile([&] (CCallHelpers& jit) { 2270 testStorePairFromOneReg(jit, 3); 2271 }); 2272 2273 initBuffer(); 2274 invoke<void>(testStorePairFromOneRegPlus3, asInt64(value2), &buffer[4]); 2275 CHECK_EQ(buffer[0], initialValue + 0); 2276 CHECK_EQ(buffer[1], initialValue + 1); 2277 CHECK_EQ(buffer[2], initialValue + 2); 2278 CHECK_EQ(buffer[3], initialValue + 3); 2279 CHECK_EQ(buffer[4], initialValue + 4); 2280 CHECK_EQ(buffer[5], initialValue + 5); 2281 CHECK_EQ(buffer[6], initialValue + 6); 2282 CHECK_EQ(buffer[7], value2); 2283 CHECK_EQ(buffer[8], value2); 2284 CHECK_EQ(buffer[9], initialValue + 9); 2285 } 2286 #endif // CPU(ARM64) 2287 1853 2288 void testProbeReadsArgumentRegisters() 1854 2289 { … … 2762 3197 2763 3198 #if CPU(ARM64) 3199 RUN(testLoadStorePair64Int64()); 3200 RUN(testLoadStorePair64Double()); 2764 3201 RUN(testMul32SignExtend()); 2765 3202 RUN(testSub32Args()); -
TabularUnified trunk/Source/JavaScriptCore/disassembler/ARM64/A64DOpcode.cpp ¶
r272892 r278856 1 1 /* 2 * Copyright (C) 2012 , 2016Apple Inc. All rights reserved.2 * Copyright (C) 2012-2021 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 73 73 OPCODE_GROUP_ENTRY(0x0b, A64DOpcodeAddSubtractExtendedRegister), 74 74 OPCODE_GROUP_ENTRY(0x0b, A64DOpcodeAddSubtractShiftedRegister), 75 OPCODE_GROUP_ENTRY(0x0c, A64DOpcodeLoadStoreRegisterPair), 76 OPCODE_GROUP_ENTRY(0x0d, A64DOpcodeLoadStoreRegisterPair), 75 77 OPCODE_GROUP_ENTRY(0x11, A64DOpcodeAddSubtractImmediate), 76 78 OPCODE_GROUP_ENTRY(0x12, A64DOpcodeMoveWide), … … 1364 1366 unsigned offsetShift; 1365 1367 if (vBit()) { 1366 appendFPRegisterName(rt(), size() );1367 appendSeparator(); 1368 appendFPRegisterName(rt2(), size() );1368 appendFPRegisterName(rt(), size() + 2); 1369 appendSeparator(); 1370 appendFPRegisterName(rt2(), size() + 2); 1369 1371 offsetShift = size() + 2; 1370 1372 } else { -
TabularUnified trunk/Source/JavaScriptCore/disassembler/ARM64/A64DOpcode.h ¶
r272892 r278856 1 1 /* 2 * Copyright (C) 2012-20 19Apple Inc. All rights reserved.2 * Copyright (C) 2012-2021 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 788 788 class A64DOpcodeLoadStoreRegisterPair : public A64DOpcodeLoadStore { 789 789 public: 790 static constexpr uint32_t mask = 0x3 a000000;790 static constexpr uint32_t mask = 0x38000000; 791 791 static constexpr uint32_t pattern = 0x28000000; 792 792
Note:
See TracChangeset
for help on using the changeset viewer.