| OLD | NEW |
| 1 //===- subzero/src/IceAssemblerARM32.cpp - Assembler for ARM32 --*- C++ -*-===// | 1 //===- subzero/src/IceAssemblerARM32.cpp - Assembler for ARM32 --*- C++ -*-===// |
| 2 // | 2 // |
| 3 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 3 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 4 // for details. All rights reserved. Use of this source code is governed by a | 4 // for details. All rights reserved. Use of this source code is governed by a |
| 5 // BSD-style license that can be found in the LICENSE file. | 5 // BSD-style license that can be found in the LICENSE file. |
| 6 // | 6 // |
| 7 // Modified by the Subzero authors. | 7 // Modified by the Subzero authors. |
| 8 // | 8 // |
| 9 //===----------------------------------------------------------------------===// | 9 //===----------------------------------------------------------------------===// |
| 10 // | 10 // |
| (...skipping 1670 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1681 // orr{s}<c> <Rd>, <Rn>, #<RotatedImm8> | 1681 // orr{s}<c> <Rd>, <Rn>, #<RotatedImm8> |
| 1682 // | 1682 // |
| 1683 // cccc0001100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, | 1683 // cccc0001100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, |
| 1684 // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. | 1684 // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. |
| 1685 constexpr const char *OrrName = "orr"; | 1685 constexpr const char *OrrName = "orr"; |
| 1686 constexpr IValueT OrrOpcode = B3 | B2; // i.e. 1100 | 1686 constexpr IValueT OrrOpcode = B3 | B2; // i.e. 1100 |
| 1687 emitType01(Cond, OrrOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags, | 1687 emitType01(Cond, OrrOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags, |
| 1688 OrrName); | 1688 OrrName); |
| 1689 } | 1689 } |
| 1690 | 1690 |
| 1691 void AssemblerARM32::pop(const Operand *OpRt, CondARM32::Cond Cond) { | 1691 void AssemblerARM32::emitStackTextOp(const Cfg *Func, const IValueT Registers, |
| 1692 CondARM32::Cond Cond, |
| 1693 const char *InstName) { |
| 1694 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1695 Str << "\t" << InstName << Cond << "\t{"; |
| 1696 bool isFirst = true; |
| 1697 for (SizeT i = 0; i < RegARM32::getNumGPRegs(); ++i) { |
| 1698 if (mask(Registers, i, 1) == 0) |
| 1699 continue; |
| 1700 if (isFirst) { |
| 1701 isFirst = false; |
| 1702 } else { |
| 1703 Str << ", "; |
| 1704 } |
| 1705 Str << RegARM32::getGPRegName(i); |
| 1706 } |
| 1707 Str << "}"; |
| 1708 } |
| 1709 |
| 1710 void AssemblerARM32::emitStackTextOp(const Cfg *Func, const Operand *OpRt, |
| 1711 CondARM32::Cond Cond, |
| 1712 const char *InstName) { |
| 1713 const IValueT Rt = encodeRegister(OpRt, "Rt", InstName); |
| 1714 const IValueT GPRegisters = 1 << Rt; |
| 1715 emitStackTextOp(Func, GPRegisters, Cond, InstName); |
| 1716 } |
| 1717 |
| 1718 template <> |
| 1719 void AssemblerARM32::pop<TextualAssembly>(const Cfg *Func, const Operand *OpRt, |
| 1720 CondARM32::Cond Cond) { |
| 1721 constexpr const char *Pop = "pop"; |
| 1722 emitStackTextOp(Func, OpRt, Cond, Pop); |
| 1723 } |
| 1724 |
| 1725 template <> |
| 1726 void AssemblerARM32::pop<BinaryAssembly>(const Cfg *Func, const Operand *OpRt, |
| 1727 CondARM32::Cond Cond) { |
| 1728 (void)Func; |
| 1692 // POP - ARM section A8.8.132, encoding A2: | 1729 // POP - ARM section A8.8.132, encoding A2: |
| 1693 // pop<c> {Rt} | 1730 // pop<c> {Rt} |
| 1694 // | 1731 // |
| 1695 // cccc010010011101dddd000000000100 where dddd=Rt and cccc=Cond. | 1732 // cccc010010011101dddd000000000100 where dddd=Rt and cccc=Cond. |
| 1696 constexpr const char *Pop = "pop"; | 1733 constexpr const char *Pop = "pop"; |
| 1697 IValueT Rt = encodeRegister(OpRt, "Rt", Pop); | 1734 const IValueT Rt = encodeRegister(OpRt, "Rt", Pop); |
| 1698 verifyRegsNotEq(Rt, "Rt", RegARM32::Encoded_Reg_sp, "sp", Pop); | 1735 verifyRegsNotEq(Rt, "Rt", RegARM32::Encoded_Reg_sp, "sp", Pop); |
| 1699 // Same as load instruction. | 1736 // Same as load instruction. |
| 1700 constexpr bool IsLoad = true; | 1737 constexpr bool IsLoad = true; |
| 1701 constexpr bool IsByte = false; | 1738 constexpr bool IsByte = false; |
| 1702 IValueT Address = encodeImmRegOffset(RegARM32::Encoded_Reg_sp, kWordSize, | 1739 IValueT Address = encodeImmRegOffset(RegARM32::Encoded_Reg_sp, kWordSize, |
| 1703 OperandARM32Mem::PostIndex); | 1740 OperandARM32Mem::PostIndex); |
| 1704 emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address, Pop); | 1741 emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address, Pop); |
| 1705 } | 1742 } |
| 1706 | 1743 |
| 1707 void AssemblerARM32::popList(const IValueT Registers, CondARM32::Cond Cond) { | 1744 template <> |
| 1745 void AssemblerARM32::popList<TextualAssembly>(const Cfg *Func, |
| 1746 const IValueT Registers, |
| 1747 CondARM32::Cond Cond) { |
| 1748 constexpr const char *PopList = "pop"; |
| 1749 emitStackTextOp(Func, Registers, Cond, PopList); |
| 1750 } |
| 1751 |
| 1752 template <> |
| 1753 void AssemblerARM32::popList<BinaryAssembly>(const Cfg *Func, |
| 1754 const IValueT Registers, |
| 1755 CondARM32::Cond Cond) { |
| 1756 (void)Func; |
| 1708 // POP - ARM section A8.*.131, encoding A1: | 1757 // POP - ARM section A8.*.131, encoding A1: |
| 1709 // pop<c> <registers> | 1758 // pop<c> <registers> |
| 1710 // | 1759 // |
| 1711 // cccc100010111101rrrrrrrrrrrrrrrr where cccc=Cond and | 1760 // cccc100010111101rrrrrrrrrrrrrrrr where cccc=Cond and |
| 1712 // rrrrrrrrrrrrrrrr=Registers (one bit for each GP register). | 1761 // rrrrrrrrrrrrrrrr=Registers (one bit for each GP register). |
| 1713 constexpr const char *PopListName = "pop {}"; | 1762 constexpr const char *PopListName = "pop {}"; |
| 1714 constexpr bool IsLoad = true; | 1763 constexpr bool IsLoad = true; |
| 1715 emitMultiMemOp(Cond, IA_W, IsLoad, RegARM32::Encoded_Reg_sp, Registers, | 1764 emitMultiMemOp(Cond, IA_W, IsLoad, RegARM32::Encoded_Reg_sp, Registers, |
| 1716 PopListName); | 1765 PopListName); |
| 1717 } | 1766 } |
| 1718 | 1767 |
| 1719 void AssemblerARM32::push(const Operand *OpRt, CondARM32::Cond Cond) { | 1768 template <> |
| 1769 void AssemblerARM32::push<TextualAssembly>(const Cfg *Func, const Operand *OpRt, |
| 1770 CondARM32::Cond Cond) { |
| 1771 constexpr const char *Push = "push"; |
| 1772 emitStackTextOp(Func, OpRt, Cond, Push); |
| 1773 } |
| 1774 |
| 1775 template <> |
| 1776 void AssemblerARM32::push<BinaryAssembly>(const Cfg *Func, const Operand *OpRt, |
| 1777 CondARM32::Cond Cond) { |
| 1778 (void)Func; |
| 1720 // PUSH - ARM section A8.8.133, encoding A2: | 1779 // PUSH - ARM section A8.8.133, encoding A2: |
| 1721 // push<c> {Rt} | 1780 // push<c> {Rt} |
| 1722 // | 1781 // |
| 1723 // cccc010100101101dddd000000000100 where dddd=Rt and cccc=Cond. | 1782 // cccc010100101101dddd000000000100 where dddd=Rt and cccc=Cond. |
| 1724 constexpr const char *Push = "push"; | 1783 constexpr const char *Push = "push"; |
| 1725 IValueT Rt = encodeRegister(OpRt, "Rt", Push); | 1784 IValueT Rt = encodeRegister(OpRt, "Rt", Push); |
| 1726 verifyRegsNotEq(Rt, "Rt", RegARM32::Encoded_Reg_sp, "sp", Push); | 1785 verifyRegsNotEq(Rt, "Rt", RegARM32::Encoded_Reg_sp, "sp", Push); |
| 1727 // Same as store instruction. | 1786 // Same as store instruction. |
| 1728 constexpr bool isLoad = false; | 1787 constexpr bool isLoad = false; |
| 1729 constexpr bool isByte = false; | 1788 constexpr bool isByte = false; |
| 1730 IValueT Address = encodeImmRegOffset(RegARM32::Encoded_Reg_sp, -kWordSize, | 1789 IValueT Address = encodeImmRegOffset(RegARM32::Encoded_Reg_sp, -kWordSize, |
| 1731 OperandARM32Mem::PreIndex); | 1790 OperandARM32Mem::PreIndex); |
| 1732 emitMemOp(Cond, kInstTypeMemImmediate, isLoad, isByte, Rt, Address, Push); | 1791 emitMemOp(Cond, kInstTypeMemImmediate, isLoad, isByte, Rt, Address, Push); |
| 1733 } | 1792 } |
| 1734 | 1793 |
| 1735 void AssemblerARM32::pushList(const IValueT Registers, CondARM32::Cond Cond) { | 1794 template <> |
| 1795 void AssemblerARM32::pushList<TextualAssembly>(const Cfg *Func, |
| 1796 const IValueT Registers, |
| 1797 CondARM32::Cond Cond) { |
| 1798 constexpr const char *PushList = "push"; |
| 1799 emitStackTextOp(Func, Registers, Cond, PushList); |
| 1800 } |
| 1801 |
| 1802 template <> |
| 1803 void AssemblerARM32::pushList<BinaryAssembly>(const Cfg *Func, |
| 1804 const IValueT Registers, |
| 1805 CondARM32::Cond Cond) { |
| 1806 (void)Func; |
| 1736 // PUSH - ARM section A8.8.133, encoding A1: | 1807 // PUSH - ARM section A8.8.133, encoding A1: |
| 1737 // push<c> <Registers> | 1808 // push<c> <Registers> |
| 1738 // | 1809 // |
| 1739 // cccc100100101101rrrrrrrrrrrrrrrr where cccc=Cond and | 1810 // cccc100100101101rrrrrrrrrrrrrrrr where cccc=Cond and |
| 1740 // rrrrrrrrrrrrrrrr=Registers (one bit for each GP register). | 1811 // rrrrrrrrrrrrrrrr=Registers (one bit for each GP register). |
| 1741 constexpr const char *PushListName = "push {}"; | 1812 constexpr const char *PushListName = "push {}"; |
| 1742 constexpr bool IsLoad = false; | 1813 constexpr bool IsLoad = false; |
| 1743 emitMultiMemOp(Cond, DB_W, IsLoad, RegARM32::Encoded_Reg_sp, Registers, | 1814 emitMultiMemOp(Cond, DB_W, IsLoad, RegARM32::Encoded_Reg_sp, Registers, |
| 1744 PushListName); | 1815 PushListName); |
| 1745 } | 1816 } |
| (...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1999 emitMulOp(Cond, UmullOpcode, RdLo, RdHi, Rn, Rm, SetFlags, UmullName); | 2070 emitMulOp(Cond, UmullOpcode, RdLo, RdHi, Rn, Rm, SetFlags, UmullName); |
| 2000 } | 2071 } |
| 2001 | 2072 |
| 2002 void AssemblerARM32::uxt(const Operand *OpRd, const Operand *OpSrc0, | 2073 void AssemblerARM32::uxt(const Operand *OpRd, const Operand *OpSrc0, |
| 2003 CondARM32::Cond Cond) { | 2074 CondARM32::Cond Cond) { |
| 2004 constexpr const char *UxtName = "uxt"; | 2075 constexpr const char *UxtName = "uxt"; |
| 2005 constexpr IValueT UxtOpcode = B26 | B25 | B23 | B22 | B21; | 2076 constexpr IValueT UxtOpcode = B26 | B25 | B23 | B22 | B21; |
| 2006 emitSignExtend(Cond, UxtOpcode, OpRd, OpSrc0, UxtName); | 2077 emitSignExtend(Cond, UxtOpcode, OpRd, OpSrc0, UxtName); |
| 2007 } | 2078 } |
| 2008 | 2079 |
| 2009 void AssemblerARM32::emitVStackOp(CondARM32::Cond Cond, IValueT Opcode, | 2080 template <> |
| 2010 const Variable *OpBaseReg, | 2081 void AssemblerARM32::emitVStackOp<TextualAssembly>( |
| 2011 SizeT NumConsecRegs, const char *InstName) { | 2082 const Cfg *Func, CondARM32::Cond Cond, IValueT Opcode, |
| 2083 const Variable *OpBaseReg, SizeT NumConsecRegs, const char *InstName) { |
| 2084 (void)Opcode; |
| 2085 if (!BuildDefs::dump()) |
| 2086 return; |
| 2012 | 2087 |
| 2088 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2089 Str << "\t" << InstName << Cond << "\t{"; |
| 2090 IValueT BaseReg = getEncodedSRegNum(OpBaseReg); |
| 2091 assert(0 < NumConsecRegs); |
| 2092 assert(NumConsecRegs <= VpushVpopMaxConsecRegs); |
| 2093 assert((BaseReg + NumConsecRegs) <= RegARM32::getNumSRegs()); |
| 2094 bool isFirst = true; |
| 2095 for (SizeT i = 0; i < NumConsecRegs; ++i) { |
| 2096 if (isFirst) { |
| 2097 isFirst = false; |
| 2098 } else { |
| 2099 Str << ", "; |
| 2100 } |
| 2101 Str << RegARM32::getSRegName(BaseReg + i); |
| 2102 } |
| 2103 Str << "}"; |
| 2104 } |
| 2105 |
| 2106 template <> |
| 2107 void AssemblerARM32::emitVStackOp<BinaryAssembly>( |
| 2108 const Cfg *Func, CondARM32::Cond Cond, IValueT Opcode, |
| 2109 const Variable *OpBaseReg, SizeT NumConsecRegs, const char *InstName) { |
| 2110 (void)Func; |
| 2013 const IValueT BaseReg = getEncodedSRegNum(OpBaseReg); | 2111 const IValueT BaseReg = getEncodedSRegNum(OpBaseReg); |
| 2014 const IValueT DLastBit = mask(BaseReg, 0, 1); // Last bit of base register. | 2112 const IValueT DLastBit = mask(BaseReg, 0, 1); // Last bit of base register. |
| 2015 const IValueT Rd = mask(BaseReg, 1, 4); // Top 4 bits of base register. | 2113 const IValueT Rd = mask(BaseReg, 1, 4); // Top 4 bits of base register. |
| 2016 assert(0 < NumConsecRegs); | 2114 assert(0 < NumConsecRegs); |
| 2017 assert(NumConsecRegs <= VpushVpopMaxConsecRegs); | 2115 assert(NumConsecRegs <= VpushVpopMaxConsecRegs); |
| 2018 assert((BaseReg + NumConsecRegs) <= RegARM32::getNumSRegs()); | 2116 assert((BaseReg + NumConsecRegs) <= RegARM32::getNumSRegs()); |
| 2019 verifyCondDefined(Cond, InstName); | 2117 verifyCondDefined(Cond, InstName); |
| 2020 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 2118 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 2021 const IValueT Encoding = Opcode | (Cond << kConditionShift) | DLastBit | | 2119 const IValueT Encoding = Opcode | (Cond << kConditionShift) | DLastBit | |
| 2022 (Rd << kRdShift) | NumConsecRegs; | 2120 (Rd << kRdShift) | NumConsecRegs; |
| 2023 emitInst(Encoding); | 2121 emitInst(Encoding); |
| 2024 } | 2122 } |
| 2025 | 2123 |
| 2026 void AssemblerARM32::vpop(const Variable *OpBaseReg, SizeT NumConsecRegs, | 2124 template <AssemblyOutputForm Form> |
| 2027 CondARM32::Cond Cond) { | 2125 void AssemblerARM32::vpop(const Cfg *Func, const Variable *OpBaseReg, |
| 2126 SizeT NumConsecRegs, CondARM32::Cond Cond) { |
| 2028 // Note: Current implementation assumes that OpBaseReg is defined using S | 2127 // Note: Current implementation assumes that OpBaseReg is defined using S |
| 2029 // registers. It doesn't implement the D register form. | 2128 // registers. It doesn't implement the D register form. |
| 2030 // | 2129 // |
| 2031 // VPOP - ARM section A8.8.367, encoding A2: | 2130 // VPOP - ARM section A8.8.367, encoding A2: |
| 2032 // vpop<c> <RegList> | 2131 // vpop<c> <RegList> |
| 2033 // | 2132 // |
| 2034 // cccc11001D111101dddd1010iiiiiiii where cccc=Cond, ddddD=BaseReg, and | 2133 // cccc11001D111101dddd1010iiiiiiii where cccc=Cond, ddddD=BaseReg, and |
| 2035 // iiiiiiii=NumConsecRegs. | 2134 // iiiiiiii=NumConsecRegs. |
| 2036 constexpr const char *VpopName = "vpop"; | 2135 constexpr const char *VpopName = "vpop"; |
| 2037 constexpr IValueT VpopOpcode = | 2136 constexpr IValueT VpopOpcode = |
| 2038 B27 | B26 | B23 | B21 | B20 | B19 | B18 | B16 | B11 | B9; | 2137 B27 | B26 | B23 | B21 | B20 | B19 | B18 | B16 | B11 | B9; |
| 2039 emitVStackOp(Cond, VpopOpcode, OpBaseReg, NumConsecRegs, VpopName); | 2138 emitVStackOp<Form>(Func, Cond, VpopOpcode, OpBaseReg, NumConsecRegs, |
| 2139 VpopName); |
| 2040 } | 2140 } |
| 2041 | 2141 |
| 2042 void AssemblerARM32::vpush(const Variable *OpBaseReg, SizeT NumConsecRegs, | 2142 template <AssemblyOutputForm Form> |
| 2043 CondARM32::Cond Cond) { | 2143 void AssemblerARM32::vpush(const Cfg *Func, const Variable *OpBaseReg, |
| 2144 SizeT NumConsecRegs, CondARM32::Cond Cond) { |
| 2044 // Note: Current implementation assumes that OpBaseReg is defined using S | 2145 // Note: Current implementation assumes that OpBaseReg is defined using S |
| 2045 // registers. It doesn't implement the D register form. | 2146 // registers. It doesn't implement the D register form. |
| 2046 // | 2147 // |
| 2047 // VPUSH - ARM section A8.8.368, encoding A2: | 2148 // VPUSH - ARM section A8.8.368, encoding A2: |
| 2048 // vpush<c> <RegList> | 2149 // vpush<c> <RegList> |
| 2049 // | 2150 // |
| 2050 // cccc11010D101101dddd1010iiiiiiii where cccc=Cond, ddddD=BaseReg, and | 2151 // cccc11010D101101dddd1010iiiiiiii where cccc=Cond, ddddD=BaseReg, and |
| 2051 // iiiiiiii=NumConsecRegs. | 2152 // iiiiiiii=NumConsecRegs. |
| 2052 constexpr const char *VpushName = "vpush"; | 2153 constexpr const char *VpushName = "vpush"; |
| 2053 constexpr IValueT VpushOpcode = | 2154 constexpr IValueT VpushOpcode = |
| 2054 B27 | B26 | B24 | B21 | B19 | B18 | B16 | B11 | B9; | 2155 B27 | B26 | B24 | B21 | B19 | B18 | B16 | B11 | B9; |
| 2055 emitVStackOp(Cond, VpushOpcode, OpBaseReg, NumConsecRegs, VpushName); | 2156 emitVStackOp<Form>(Func, Cond, VpushOpcode, OpBaseReg, NumConsecRegs, |
| 2157 VpushName); |
| 2056 } | 2158 } |
| 2057 | 2159 |
| 2160 // Force template instantiations. |
| 2161 |
| 2162 template void AssemblerARM32::vpop<TextualAssembly>(const Cfg *Func, |
| 2163 const Variable *OpBaseReg, |
| 2164 SizeT NumConsecRegs, |
| 2165 CondARM32::Cond Cond); |
| 2166 |
| 2167 template void AssemblerARM32::vpop<BinaryAssembly>(const Cfg *Func, |
| 2168 const Variable *OpBaseReg, |
| 2169 SizeT NumConsecRegs, |
| 2170 CondARM32::Cond Cond); |
| 2171 |
| 2172 template void AssemblerARM32::vpush<TextualAssembly>(const Cfg *Func, |
| 2173 const Variable *OpBaseReg, |
| 2174 SizeT NumConsecRegs, |
| 2175 CondARM32::Cond Cond); |
| 2176 |
| 2177 template void AssemblerARM32::vpush<BinaryAssembly>(const Cfg *Func, |
| 2178 const Variable *OpBaseReg, |
| 2179 SizeT NumConsecRegs, |
| 2180 CondARM32::Cond Cond); |
| 2181 |
| 2058 } // end of namespace ARM32 | 2182 } // end of namespace ARM32 |
| 2059 } // end of namespace Ice | 2183 } // end of namespace Ice |
| OLD | NEW |