| OLD | NEW |
| 1 //===- subzero/src/IceAssemblerX86BaseImpl.h - base x86 assembler -*- C++ -*-=// | 1 //===- subzero/src/IceAssemblerX86BaseImpl.h - base x86 assembler -*- C++ -*-=// |
| 2 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 2 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 3 // for details. All rights reserved. Use of this source code is governed by a | 3 // for details. All rights reserved. Use of this source code is governed by a |
| 4 // BSD-style license that can be found in the LICENSE file. | 4 // BSD-style license that can be found in the LICENSE file. |
| 5 // | 5 // |
| 6 // Modified by the Subzero authors. | 6 // Modified by the Subzero authors. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 // | 9 // |
| 10 // The Subzero Code Generator | 10 // The Subzero Code Generator |
| (...skipping 1050 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1061 emitUint8(0x73); | 1061 emitUint8(0x73); |
| 1062 } else { | 1062 } else { |
| 1063 assert(Ty == IceType_i32 || Ty == IceType_f32 || Ty == IceType_v4f32); | 1063 assert(Ty == IceType_i32 || Ty == IceType_f32 || Ty == IceType_v4f32); |
| 1064 emitUint8(0x72); | 1064 emitUint8(0x72); |
| 1065 } | 1065 } |
| 1066 emitRegisterOperand(2, gprEncoding(dst)); | 1066 emitRegisterOperand(2, gprEncoding(dst)); |
| 1067 emitUint8(imm.value() & 0xFF); | 1067 emitUint8(imm.value() & 0xFF); |
| 1068 } | 1068 } |
| 1069 | 1069 |
| 1070 // {add,sub,mul,div}ps are given a Ty parameter for consistency with | 1070 // {add,sub,mul,div}ps are given a Ty parameter for consistency with |
| 1071 // {add,sub,mul,div}ss. In the future, when the PNaCl ABI allows | 1071 // {add,sub,mul,div}ss. In the future, when the PNaCl ABI allows addpd, etc., |
| 1072 // addpd, etc., we can use the Ty parameter to decide on adding | 1072 // we can use the Ty parameter to decide on adding a 0x66 prefix. |
| 1073 // a 0x66 prefix. | |
| 1074 template <class Machine> | 1073 template <class Machine> |
| 1075 void AssemblerX86Base<Machine>::addps(Type /* Ty */, | 1074 void AssemblerX86Base<Machine>::addps(Type /* Ty */, |
| 1076 typename Traits::XmmRegister dst, | 1075 typename Traits::XmmRegister dst, |
| 1077 typename Traits::XmmRegister src) { | 1076 typename Traits::XmmRegister src) { |
| 1078 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 1077 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 1079 emitRexRB(RexTypeIrrelevant, dst, src); | 1078 emitRexRB(RexTypeIrrelevant, dst, src); |
| 1080 emitUint8(0x0F); | 1079 emitUint8(0x0F); |
| 1081 emitUint8(0x58); | 1080 emitUint8(0x58); |
| 1082 emitXmmRegisterOperand(dst, src); | 1081 emitXmmRegisterOperand(dst, src); |
| 1083 } | 1082 } |
| (...skipping 745 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1829 emitUint8(0x0F); | 1828 emitUint8(0x0F); |
| 1830 emitUint8(0xC5); | 1829 emitUint8(0xC5); |
| 1831 emitXmmRegisterOperand(dst, src); | 1830 emitXmmRegisterOperand(dst, src); |
| 1832 emitUint8(imm.value()); | 1831 emitUint8(imm.value()); |
| 1833 } else { | 1832 } else { |
| 1834 emitUint8(0x66); | 1833 emitUint8(0x66); |
| 1835 emitRexRB(Ty, src, dst); | 1834 emitRexRB(Ty, src, dst); |
| 1836 emitUint8(0x0F); | 1835 emitUint8(0x0F); |
| 1837 emitUint8(0x3A); | 1836 emitUint8(0x3A); |
| 1838 emitUint8(isByteSizedType(Ty) ? 0x14 : 0x16); | 1837 emitUint8(isByteSizedType(Ty) ? 0x14 : 0x16); |
| 1839 // SSE 4.1 versions are "MRI" because dst can be mem, while | 1838 // SSE 4.1 versions are "MRI" because dst can be mem, while pextrw (SSE2) |
| 1840 // pextrw (SSE2) is RMI because dst must be reg. | 1839 // is RMI because dst must be reg. |
| 1841 emitXmmRegisterOperand(src, dst); | 1840 emitXmmRegisterOperand(src, dst); |
| 1842 emitUint8(imm.value()); | 1841 emitUint8(imm.value()); |
| 1843 } | 1842 } |
| 1844 } | 1843 } |
| 1845 | 1844 |
| 1846 template <class Machine> | 1845 template <class Machine> |
| 1847 void AssemblerX86Base<Machine>::pmovsxdq(typename Traits::XmmRegister dst, | 1846 void AssemblerX86Base<Machine>::pmovsxdq(typename Traits::XmmRegister dst, |
| 1848 typename Traits::XmmRegister src) { | 1847 typename Traits::XmmRegister src) { |
| 1849 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 1848 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 1850 emitUint8(0x66); | 1849 emitUint8(0x66); |
| (...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2140 emitUint8(0x84); | 2139 emitUint8(0x84); |
| 2141 else | 2140 else |
| 2142 emitUint8(0x85); | 2141 emitUint8(0x85); |
| 2143 emitOperand(gprEncoding(reg), addr); | 2142 emitOperand(gprEncoding(reg), addr); |
| 2144 } | 2143 } |
| 2145 | 2144 |
| 2146 template <class Machine> | 2145 template <class Machine> |
| 2147 void AssemblerX86Base<Machine>::test(Type Ty, typename Traits::GPRRegister reg, | 2146 void AssemblerX86Base<Machine>::test(Type Ty, typename Traits::GPRRegister reg, |
| 2148 const Immediate &immediate) { | 2147 const Immediate &immediate) { |
| 2149 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 2148 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 2150 // For registers that have a byte variant (EAX, EBX, ECX, and EDX) | 2149 // For registers that have a byte variant (EAX, EBX, ECX, and EDX) we only |
| 2151 // we only test the byte register to keep the encoding short. | 2150 // test the byte register to keep the encoding short. This is legal even if |
| 2152 // This is legal even if the register had high bits set since | 2151 // the register had high bits set since this only sets flags registers based |
| 2153 // this only sets flags registers based on the "AND" of the two operands, | 2152 // on the "AND" of the two operands, and the immediate had zeros at those |
| 2154 // and the immediate had zeros at those high bits. | 2153 // high bits. |
| 2155 if (immediate.is_uint8() && reg <= Traits::Last8BitGPR) { | 2154 if (immediate.is_uint8() && reg <= Traits::Last8BitGPR) { |
| 2156 // Use zero-extended 8-bit immediate. | 2155 // Use zero-extended 8-bit immediate. |
| 2157 emitRexB(Ty, reg); | 2156 emitRexB(Ty, reg); |
| 2158 if (reg == Traits::Encoded_Reg_Accumulator) { | 2157 if (reg == Traits::Encoded_Reg_Accumulator) { |
| 2159 emitUint8(0xA8); | 2158 emitUint8(0xA8); |
| 2160 } else { | 2159 } else { |
| 2161 emitUint8(0xF6); | 2160 emitUint8(0xF6); |
| 2162 emitUint8(0xC0 + gprEncoding(reg)); | 2161 emitUint8(0xC0 + gprEncoding(reg)); |
| 2163 } | 2162 } |
| 2164 emitUint8(immediate.value() & 0xFF); | 2163 emitUint8(immediate.value() & 0xFF); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2176 emitRegisterOperand(0, gprEncoding(reg)); | 2175 emitRegisterOperand(0, gprEncoding(reg)); |
| 2177 emitImmediate(Ty, immediate); | 2176 emitImmediate(Ty, immediate); |
| 2178 } | 2177 } |
| 2179 } | 2178 } |
| 2180 | 2179 |
| 2181 template <class Machine> | 2180 template <class Machine> |
| 2182 void AssemblerX86Base<Machine>::test(Type Ty, | 2181 void AssemblerX86Base<Machine>::test(Type Ty, |
| 2183 const typename Traits::Address &addr, | 2182 const typename Traits::Address &addr, |
| 2184 const Immediate &immediate) { | 2183 const Immediate &immediate) { |
| 2185 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 2184 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 2186 // If the immediate is short, we only test the byte addr to keep the | 2185 // If the immediate is short, we only test the byte addr to keep the encoding |
| 2187 // encoding short. | 2186 // short. |
| 2188 if (immediate.is_uint8()) { | 2187 if (immediate.is_uint8()) { |
| 2189 // Use zero-extended 8-bit immediate. | 2188 // Use zero-extended 8-bit immediate. |
| 2190 emitRex(Ty, addr, RexRegIrrelevant); | 2189 emitRex(Ty, addr, RexRegIrrelevant); |
| 2191 emitUint8(0xF6); | 2190 emitUint8(0xF6); |
| 2192 emitOperand(0, addr); | 2191 emitOperand(0, addr); |
| 2193 emitUint8(immediate.value() & 0xFF); | 2192 emitUint8(immediate.value() & 0xFF); |
| 2194 } else { | 2193 } else { |
| 2195 if (Ty == IceType_i16) | 2194 if (Ty == IceType_i16) |
| 2196 emitOperandSizeOverride(); | 2195 emitOperandSizeOverride(); |
| 2197 emitRex(Ty, addr, RexRegIrrelevant); | 2196 emitRex(Ty, addr, RexRegIrrelevant); |
| (...skipping 811 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3009 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 3008 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 3010 if (label->isBound()) { | 3009 if (label->isBound()) { |
| 3011 static const int kShortSize = 2; | 3010 static const int kShortSize = 2; |
| 3012 static const int kLongSize = 6; | 3011 static const int kLongSize = 6; |
| 3013 intptr_t offset = label->getPosition() - Buffer.size(); | 3012 intptr_t offset = label->getPosition() - Buffer.size(); |
| 3014 assert(offset <= 0); | 3013 assert(offset <= 0); |
| 3015 if (Utils::IsInt(8, offset - kShortSize)) { | 3014 if (Utils::IsInt(8, offset - kShortSize)) { |
| 3016 // TODO(stichnot): Here and in jmp(), we may need to be more | 3015 // TODO(stichnot): Here and in jmp(), we may need to be more |
| 3017 // conservative about the backward branch distance if the branch | 3016 // conservative about the backward branch distance if the branch |
| 3018 // instruction is within a bundle_lock sequence, because the | 3017 // instruction is within a bundle_lock sequence, because the |
| 3019 // distance may increase when padding is added. This isn't an | 3018 // distance may increase when padding is added. This isn't an issue for |
| 3020 // issue for branches outside a bundle_lock, because if padding | 3019 // branches outside a bundle_lock, because if padding is added, the retry |
| 3021 // is added, the retry may change it to a long backward branch | 3020 // may change it to a long backward branch without affecting any of the |
| 3022 // without affecting any of the bookkeeping. | 3021 // bookkeeping. |
| 3023 emitUint8(0x70 + condition); | 3022 emitUint8(0x70 + condition); |
| 3024 emitUint8((offset - kShortSize) & 0xFF); | 3023 emitUint8((offset - kShortSize) & 0xFF); |
| 3025 } else { | 3024 } else { |
| 3026 emitUint8(0x0F); | 3025 emitUint8(0x0F); |
| 3027 emitUint8(0x80 + condition); | 3026 emitUint8(0x80 + condition); |
| 3028 emitInt32(offset - kLongSize); | 3027 emitInt32(offset - kLongSize); |
| 3029 } | 3028 } |
| 3030 } else if (near) { | 3029 } else if (near) { |
| 3031 emitUint8(0x70 + condition); | 3030 emitUint8(0x70 + condition); |
| 3032 emitNearLabelLink(label); | 3031 emitNearLabelLink(label); |
| (...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3394 (void)shifter; | 3393 (void)shifter; |
| 3395 if (Ty == IceType_i16) | 3394 if (Ty == IceType_i16) |
| 3396 emitOperandSizeOverride(); | 3395 emitOperandSizeOverride(); |
| 3397 emitRexB(Ty, operand.rm()); | 3396 emitRexB(Ty, operand.rm()); |
| 3398 emitUint8(isByteSizedArithType(Ty) ? 0xD2 : 0xD3); | 3397 emitUint8(isByteSizedArithType(Ty) ? 0xD2 : 0xD3); |
| 3399 emitOperand(rm, operand); | 3398 emitOperand(rm, operand); |
| 3400 } | 3399 } |
| 3401 | 3400 |
| 3402 } // end of namespace X86Internal | 3401 } // end of namespace X86Internal |
| 3403 } // end of namespace Ice | 3402 } // end of namespace Ice |
| OLD | NEW |