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 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
292 void AssemblerX86Base<TraitsType>::mov(Type Ty, const Address &dst, | 292 void AssemblerX86Base<TraitsType>::mov(Type Ty, const Address &dst, |
293 const Immediate &imm) { | 293 const Immediate &imm) { |
294 assert(Ty != IceType_i64 && "i64 not supported yet."); | 294 assert(Ty != IceType_i64 && "i64 not supported yet."); |
295 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 295 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
296 if (Ty == IceType_i16) | 296 if (Ty == IceType_i16) |
297 emitOperandSizeOverride(); | 297 emitOperandSizeOverride(); |
298 emitAddrSizeOverridePrefix(); | 298 emitAddrSizeOverridePrefix(); |
299 emitRex(Ty, dst, RexRegIrrelevant); | 299 emitRex(Ty, dst, RexRegIrrelevant); |
300 if (isByteSizedType(Ty)) { | 300 if (isByteSizedType(Ty)) { |
301 emitUint8(0xC6); | 301 emitUint8(0xC6); |
302 emitOperand(0, dst); | 302 static constexpr RelocOffsetT OffsetFromNextInstruction = 1; |
Jim Stichnoth
2016/01/23 01:57:46
What do you think about using typeWidthInBytes(Ty)
John
2016/01/26 19:44:25
Discussed offline. keeping as is.
| |
303 emitOperand(0, dst, OffsetFromNextInstruction); | |
303 emitUint8(imm.value() & 0xFF); | 304 emitUint8(imm.value() & 0xFF); |
304 } else { | 305 } else { |
305 emitUint8(0xC7); | 306 emitUint8(0xC7); |
306 emitOperand(0, dst); | 307 const uint8_t OffsetFromNextInstruction = Ty == IceType_i16 ? 2 : 4; |
308 emitOperand(0, dst, OffsetFromNextInstruction); | |
307 emitImmediate(Ty, imm); | 309 emitImmediate(Ty, imm); |
308 } | 310 } |
309 } | 311 } |
310 | 312 |
311 template <typename TraitsType> | 313 template <typename TraitsType> |
312 template <typename T> | 314 template <typename T> |
313 typename std::enable_if<T::Is64Bit, void>::type | 315 typename std::enable_if<T::Is64Bit, void>::type |
314 AssemblerX86Base<TraitsType>::movabs(const GPRRegister Dst, uint64_t Imm64) { | 316 AssemblerX86Base<TraitsType>::movabs(const GPRRegister Dst, uint64_t Imm64) { |
315 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 317 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
316 const bool NeedsRexW = (Imm64 & ~0xFFFFFFFFull) != 0; | 318 const bool NeedsRexW = (Imm64 & ~0xFFFFFFFFull) != 0; |
(...skipping 1105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1422 void AssemblerX86Base<TraitsType>::cmpps(Type Ty, XmmRegister dst, | 1424 void AssemblerX86Base<TraitsType>::cmpps(Type Ty, XmmRegister dst, |
1423 const Address &src, | 1425 const Address &src, |
1424 CmppsCond CmpCondition) { | 1426 CmppsCond CmpCondition) { |
1425 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 1427 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
1426 if (Ty == IceType_f64) | 1428 if (Ty == IceType_f64) |
1427 emitUint8(0x66); | 1429 emitUint8(0x66); |
1428 emitAddrSizeOverridePrefix(); | 1430 emitAddrSizeOverridePrefix(); |
1429 emitRex(RexTypeIrrelevant, src, dst); | 1431 emitRex(RexTypeIrrelevant, src, dst); |
1430 emitUint8(0x0F); | 1432 emitUint8(0x0F); |
1431 emitUint8(0xC2); | 1433 emitUint8(0xC2); |
1432 emitOperand(gprEncoding(dst), src); | 1434 static constexpr RelocOffsetT OffsetFromNextInstruction = 1; |
1435 emitOperand(gprEncoding(dst), src, OffsetFromNextInstruction); | |
1433 emitUint8(CmpCondition); | 1436 emitUint8(CmpCondition); |
1434 } | 1437 } |
1435 | 1438 |
1436 template <typename TraitsType> | 1439 template <typename TraitsType> |
1437 void AssemblerX86Base<TraitsType>::sqrtps(XmmRegister dst) { | 1440 void AssemblerX86Base<TraitsType>::sqrtps(XmmRegister dst) { |
1438 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 1441 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
1439 emitRexRB(RexTypeIrrelevant, dst, dst); | 1442 emitRexRB(RexTypeIrrelevant, dst, dst); |
1440 emitUint8(0x0F); | 1443 emitUint8(0x0F); |
1441 emitUint8(0x51); | 1444 emitUint8(0x51); |
1442 emitXmmRegisterOperand(dst, dst); | 1445 emitXmmRegisterOperand(dst, dst); |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1544 template <typename TraitsType> | 1547 template <typename TraitsType> |
1545 void AssemblerX86Base<TraitsType>::pshufd(Type /* Ty */, XmmRegister dst, | 1548 void AssemblerX86Base<TraitsType>::pshufd(Type /* Ty */, XmmRegister dst, |
1546 const Address &src, | 1549 const Address &src, |
1547 const Immediate &imm) { | 1550 const Immediate &imm) { |
1548 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 1551 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
1549 emitUint8(0x66); | 1552 emitUint8(0x66); |
1550 emitAddrSizeOverridePrefix(); | 1553 emitAddrSizeOverridePrefix(); |
1551 emitRex(RexTypeIrrelevant, src, dst); | 1554 emitRex(RexTypeIrrelevant, src, dst); |
1552 emitUint8(0x0F); | 1555 emitUint8(0x0F); |
1553 emitUint8(0x70); | 1556 emitUint8(0x70); |
1554 emitOperand(gprEncoding(dst), src); | 1557 static constexpr RelocOffsetT OffsetFromNextInstruction = 1; |
1558 emitOperand(gprEncoding(dst), src, OffsetFromNextInstruction); | |
1555 assert(imm.is_uint8()); | 1559 assert(imm.is_uint8()); |
1556 emitUint8(imm.value()); | 1560 emitUint8(imm.value()); |
1557 } | 1561 } |
1558 | 1562 |
1559 template <typename TraitsType> | 1563 template <typename TraitsType> |
1560 void AssemblerX86Base<TraitsType>::shufps(Type /* Ty */, XmmRegister dst, | 1564 void AssemblerX86Base<TraitsType>::shufps(Type /* Ty */, XmmRegister dst, |
1561 XmmRegister src, | 1565 XmmRegister src, |
1562 const Immediate &imm) { | 1566 const Immediate &imm) { |
1563 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 1567 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
1564 emitRexRB(RexTypeIrrelevant, dst, src); | 1568 emitRexRB(RexTypeIrrelevant, dst, src); |
1565 emitUint8(0x0F); | 1569 emitUint8(0x0F); |
1566 emitUint8(0xC6); | 1570 emitUint8(0xC6); |
1567 emitXmmRegisterOperand(dst, src); | 1571 emitXmmRegisterOperand(dst, src); |
1568 assert(imm.is_uint8()); | 1572 assert(imm.is_uint8()); |
1569 emitUint8(imm.value()); | 1573 emitUint8(imm.value()); |
1570 } | 1574 } |
1571 | 1575 |
1572 template <typename TraitsType> | 1576 template <typename TraitsType> |
1573 void AssemblerX86Base<TraitsType>::shufps(Type /* Ty */, XmmRegister dst, | 1577 void AssemblerX86Base<TraitsType>::shufps(Type /* Ty */, XmmRegister dst, |
1574 const Address &src, | 1578 const Address &src, |
1575 const Immediate &imm) { | 1579 const Immediate &imm) { |
1576 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 1580 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
1577 emitAddrSizeOverridePrefix(); | 1581 emitAddrSizeOverridePrefix(); |
1578 emitRex(RexTypeIrrelevant, src, dst); | 1582 emitRex(RexTypeIrrelevant, src, dst); |
1579 emitUint8(0x0F); | 1583 emitUint8(0x0F); |
1580 emitUint8(0xC6); | 1584 emitUint8(0xC6); |
1581 emitOperand(gprEncoding(dst), src); | 1585 static constexpr RelocOffsetT OffsetFromNextInstruction = 1; |
1586 emitOperand(gprEncoding(dst), src, OffsetFromNextInstruction); | |
1582 assert(imm.is_uint8()); | 1587 assert(imm.is_uint8()); |
1583 emitUint8(imm.value()); | 1588 emitUint8(imm.value()); |
1584 } | 1589 } |
1585 | 1590 |
1586 template <typename TraitsType> | 1591 template <typename TraitsType> |
1587 void AssemblerX86Base<TraitsType>::sqrtpd(XmmRegister dst) { | 1592 void AssemblerX86Base<TraitsType>::sqrtpd(XmmRegister dst) { |
1588 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 1593 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
1589 emitUint8(0x66); | 1594 emitUint8(0x66); |
1590 emitRexRB(RexTypeIrrelevant, dst, dst); | 1595 emitRexRB(RexTypeIrrelevant, dst, dst); |
1591 emitUint8(0x0F); | 1596 emitUint8(0x0F); |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1823 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 1828 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
1824 assert(imm.is_uint8()); | 1829 assert(imm.is_uint8()); |
1825 assert(isVectorFloatingType(Ty)); | 1830 assert(isVectorFloatingType(Ty)); |
1826 (void)Ty; | 1831 (void)Ty; |
1827 emitUint8(0x66); | 1832 emitUint8(0x66); |
1828 emitAddrSizeOverridePrefix(); | 1833 emitAddrSizeOverridePrefix(); |
1829 emitRex(RexTypeIrrelevant, src, dst); | 1834 emitRex(RexTypeIrrelevant, src, dst); |
1830 emitUint8(0x0F); | 1835 emitUint8(0x0F); |
1831 emitUint8(0x3A); | 1836 emitUint8(0x3A); |
1832 emitUint8(0x21); | 1837 emitUint8(0x21); |
1833 emitOperand(gprEncoding(dst), src); | 1838 static constexpr RelocOffsetT OffsetFromNextInstruction = 1; |
1839 emitOperand(gprEncoding(dst), src, OffsetFromNextInstruction); | |
1834 emitUint8(imm.value()); | 1840 emitUint8(imm.value()); |
1835 } | 1841 } |
1836 | 1842 |
1837 template <typename TraitsType> | 1843 template <typename TraitsType> |
1838 void AssemblerX86Base<TraitsType>::pinsr(Type Ty, XmmRegister dst, | 1844 void AssemblerX86Base<TraitsType>::pinsr(Type Ty, XmmRegister dst, |
1839 GPRRegister src, | 1845 GPRRegister src, |
1840 const Immediate &imm) { | 1846 const Immediate &imm) { |
1841 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 1847 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
1842 assert(imm.is_uint8()); | 1848 assert(imm.is_uint8()); |
1843 emitUint8(0x66); | 1849 emitUint8(0x66); |
(...skipping 18 matching lines...) Expand all Loading... | |
1862 emitUint8(0x66); | 1868 emitUint8(0x66); |
1863 emitAddrSizeOverridePrefix(); | 1869 emitAddrSizeOverridePrefix(); |
1864 emitRex(RexTypeIrrelevant, src, dst); | 1870 emitRex(RexTypeIrrelevant, src, dst); |
1865 emitUint8(0x0F); | 1871 emitUint8(0x0F); |
1866 if (Ty == IceType_i16) { | 1872 if (Ty == IceType_i16) { |
1867 emitUint8(0xC4); | 1873 emitUint8(0xC4); |
1868 } else { | 1874 } else { |
1869 emitUint8(0x3A); | 1875 emitUint8(0x3A); |
1870 emitUint8(isByteSizedType(Ty) ? 0x20 : 0x22); | 1876 emitUint8(isByteSizedType(Ty) ? 0x20 : 0x22); |
1871 } | 1877 } |
1872 emitOperand(gprEncoding(dst), src); | 1878 static constexpr RelocOffsetT OffsetFromNextInstruction = 1; |
1879 emitOperand(gprEncoding(dst), src, OffsetFromNextInstruction); | |
1873 emitUint8(imm.value()); | 1880 emitUint8(imm.value()); |
1874 } | 1881 } |
1875 | 1882 |
1876 template <typename TraitsType> | 1883 template <typename TraitsType> |
1877 void AssemblerX86Base<TraitsType>::pextr(Type Ty, GPRRegister dst, | 1884 void AssemblerX86Base<TraitsType>::pextr(Type Ty, GPRRegister dst, |
1878 XmmRegister src, | 1885 XmmRegister src, |
1879 const Immediate &imm) { | 1886 const Immediate &imm) { |
1880 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 1887 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
1881 assert(imm.is_uint8()); | 1888 assert(imm.is_uint8()); |
1882 if (Ty == IceType_i16) { | 1889 if (Ty == IceType_i16) { |
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2237 void AssemblerX86Base<TraitsType>::test(Type Ty, const Address &addr, | 2244 void AssemblerX86Base<TraitsType>::test(Type Ty, const Address &addr, |
2238 const Immediate &immediate) { | 2245 const Immediate &immediate) { |
2239 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 2246 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
2240 // If the immediate is short, we only test the byte addr to keep the encoding | 2247 // If the immediate is short, we only test the byte addr to keep the encoding |
2241 // short. | 2248 // short. |
2242 if (immediate.is_uint8()) { | 2249 if (immediate.is_uint8()) { |
2243 // Use zero-extended 8-bit immediate. | 2250 // Use zero-extended 8-bit immediate. |
2244 emitAddrSizeOverridePrefix(); | 2251 emitAddrSizeOverridePrefix(); |
2245 emitRex(Ty, addr, RexRegIrrelevant); | 2252 emitRex(Ty, addr, RexRegIrrelevant); |
2246 emitUint8(0xF6); | 2253 emitUint8(0xF6); |
2247 emitOperand(0, addr); | 2254 static constexpr RelocOffsetT OffsetFromNextInstruction = 1; |
2255 emitOperand(0, addr, OffsetFromNextInstruction); | |
2248 emitUint8(immediate.value() & 0xFF); | 2256 emitUint8(immediate.value() & 0xFF); |
2249 } else { | 2257 } else { |
2250 if (Ty == IceType_i16) | 2258 if (Ty == IceType_i16) |
2251 emitOperandSizeOverride(); | 2259 emitOperandSizeOverride(); |
2252 emitAddrSizeOverridePrefix(); | 2260 emitAddrSizeOverridePrefix(); |
2253 emitRex(Ty, addr, RexRegIrrelevant); | 2261 emitRex(Ty, addr, RexRegIrrelevant); |
2254 emitUint8(0xF7); | 2262 emitUint8(0xF7); |
2255 emitOperand(0, addr); | 2263 const uint8_t OffsetFromNextInstruction = Ty == IceType_i16 ? 2 : 4; |
2264 emitOperand(0, addr, OffsetFromNextInstruction); | |
2256 emitImmediate(Ty, immediate); | 2265 emitImmediate(Ty, immediate); |
2257 } | 2266 } |
2258 } | 2267 } |
2259 | 2268 |
2260 template <typename TraitsType> | 2269 template <typename TraitsType> |
2261 void AssemblerX86Base<TraitsType>::And(Type Ty, GPRRegister dst, | 2270 void AssemblerX86Base<TraitsType>::And(Type Ty, GPRRegister dst, |
2262 GPRRegister src) { | 2271 GPRRegister src) { |
2263 arith_int<4>(Ty, dst, src); | 2272 arith_int<4>(Ty, dst, src); |
2264 } | 2273 } |
2265 | 2274 |
(...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2646 const Address &address, | 2655 const Address &address, |
2647 const Immediate &imm) { | 2656 const Immediate &imm) { |
2648 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 2657 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
2649 assert(Ty == IceType_i16 || Ty == IceType_i32); | 2658 assert(Ty == IceType_i16 || Ty == IceType_i32); |
2650 if (Ty == IceType_i16) | 2659 if (Ty == IceType_i16) |
2651 emitOperandSizeOverride(); | 2660 emitOperandSizeOverride(); |
2652 emitAddrSizeOverridePrefix(); | 2661 emitAddrSizeOverridePrefix(); |
2653 emitRex(Ty, address, dst); | 2662 emitRex(Ty, address, dst); |
2654 if (imm.is_int8()) { | 2663 if (imm.is_int8()) { |
2655 emitUint8(0x6B); | 2664 emitUint8(0x6B); |
2656 emitOperand(gprEncoding(dst), address); | 2665 static constexpr RelocOffsetT OffsetFromNextInstruction = 1; |
2666 emitOperand(gprEncoding(dst), address, OffsetFromNextInstruction); | |
2657 emitUint8(imm.value() & 0xFF); | 2667 emitUint8(imm.value() & 0xFF); |
2658 } else { | 2668 } else { |
2659 emitUint8(0x69); | 2669 emitUint8(0x69); |
2660 emitOperand(gprEncoding(dst), address); | 2670 const uint8_t OffsetFromNextInstruction = Ty == IceType_i16 ? 2 : 4; |
2671 emitOperand(gprEncoding(dst), address, OffsetFromNextInstruction); | |
2661 emitImmediate(Ty, imm); | 2672 emitImmediate(Ty, imm); |
2662 } | 2673 } |
2663 } | 2674 } |
2664 | 2675 |
2665 template <typename TraitsType> | 2676 template <typename TraitsType> |
2666 void AssemblerX86Base<TraitsType>::mul(Type Ty, GPRRegister reg) { | 2677 void AssemblerX86Base<TraitsType>::mul(Type Ty, GPRRegister reg) { |
2667 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 2678 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
2668 if (Ty == IceType_i16) | 2679 if (Ty == IceType_i16) |
2669 emitOperandSizeOverride(); | 2680 emitOperandSizeOverride(); |
2670 emitRexB(Ty, reg); | 2681 emitRexB(Ty, reg); |
(...skipping 668 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3339 while (L->hasNear()) { | 3350 while (L->hasNear()) { |
3340 intptr_t Position = L->getNearPosition(); | 3351 intptr_t Position = L->getNearPosition(); |
3341 const intptr_t Offset = Bound - (Position + 1); | 3352 const intptr_t Offset = Bound - (Position + 1); |
3342 assert(Utils::IsInt(8, Offset)); | 3353 assert(Utils::IsInt(8, Offset)); |
3343 Buffer.store<int8_t>(Position, Offset); | 3354 Buffer.store<int8_t>(Position, Offset); |
3344 } | 3355 } |
3345 L->bindTo(Bound); | 3356 L->bindTo(Bound); |
3346 } | 3357 } |
3347 | 3358 |
3348 template <typename TraitsType> | 3359 template <typename TraitsType> |
3349 void AssemblerX86Base<TraitsType>::emitOperand(int rm, const Operand &operand) { | 3360 void AssemblerX86Base<TraitsType>::emitOperand(int rm, const Operand &operand, |
3361 RelocOffsetT Addend) { | |
3350 assert(rm >= 0 && rm < 8); | 3362 assert(rm >= 0 && rm < 8); |
3351 const intptr_t length = operand.length_; | 3363 const intptr_t length = operand.length_; |
3352 assert(length > 0); | 3364 assert(length > 0); |
3353 intptr_t displacement_start = 1; | 3365 intptr_t displacement_start = 1; |
3354 // Emit the ModRM byte updated with the given RM value. | 3366 // Emit the ModRM byte updated with the given RM value. |
3355 assert((operand.encoding_[0] & 0x38) == 0); | 3367 assert((operand.encoding_[0] & 0x38) == 0); |
3356 emitUint8(operand.encoding_[0] + (rm << 3)); | 3368 emitUint8(operand.encoding_[0] + (rm << 3)); |
3357 // Whenever the addressing mode is not register indirect, using esp == 0x4 | 3369 // Whenever the addressing mode is not register indirect, using esp == 0x4 |
3358 // as the register operation indicates an SIB byte follows. | 3370 // as the register operation indicates an SIB byte follows. |
3359 if (((operand.encoding_[0] & 0xc0) != 0xc0) && | 3371 if (((operand.encoding_[0] & 0xc0) != 0xc0) && |
3360 ((operand.encoding_[0] & 0x07) == 0x04)) { | 3372 ((operand.encoding_[0] & 0x07) == 0x04)) { |
3361 emitUint8(operand.encoding_[1]); | 3373 emitUint8(operand.encoding_[1]); |
3362 displacement_start = 2; | 3374 displacement_start = 2; |
3363 } | 3375 } |
3364 // Emit the displacement and the fixup that affects it, if any. | 3376 // Emit the displacement and the fixup that affects it, if any. |
3365 if (operand.fixup()) { | 3377 AssemblerFixup *Fixup = operand.fixup(); |
3366 emitFixup(operand.fixup()); | 3378 if (Fixup != nullptr) { |
3379 emitFixup(Fixup); | |
3367 assert(length - displacement_start == 4); | 3380 assert(length - displacement_start == 4); |
3381 if (fixupIsPCRel(Fixup->kind())) { | |
3382 Fixup->set_addend(-Addend); | |
3383 int32_t Offset; | |
3384 memmove(&Offset, &operand.encoding_[displacement_start], sizeof(Offset)); | |
3385 Offset -= Addend; | |
3386 emitInt32(Offset); | |
3387 return; | |
3388 } | |
3368 } | 3389 } |
3369 for (intptr_t i = displacement_start; i < length; i++) { | 3390 for (intptr_t i = displacement_start; i < length; i++) { |
3370 emitUint8(operand.encoding_[i]); | 3391 emitUint8(operand.encoding_[i]); |
3371 } | 3392 } |
3372 } | 3393 } |
3373 | 3394 |
3374 template <typename TraitsType> | 3395 template <typename TraitsType> |
3375 void AssemblerX86Base<TraitsType>::emitImmediate(Type Ty, | 3396 void AssemblerX86Base<TraitsType>::emitImmediate(Type Ty, |
3376 const Immediate &imm) { | 3397 const Immediate &imm) { |
3398 auto *const Fixup = imm.fixup(); | |
Jim Stichnoth
2016/01/23 01:57:46
Fortunately I didn't have to scan too far from her
John
2016/01/26 19:44:25
My arguments for auto here:
1) the following line
| |
3377 if (Ty == IceType_i16) { | 3399 if (Ty == IceType_i16) { |
3378 assert(!imm.fixup()); | 3400 assert(Fixup == nullptr); |
3379 emitInt16(imm.value()); | 3401 emitInt16(imm.value()); |
3380 } else { | 3402 return; |
3381 if (imm.fixup()) { | |
3382 emitFixup(imm.fixup()); | |
3383 } | |
3384 emitInt32(imm.value()); | |
3385 } | 3403 } |
3404 | |
3405 if (Fixup != nullptr) { | |
3406 emitFixup(Fixup); | |
3407 } | |
3408 emitInt32(imm.value()); | |
3386 } | 3409 } |
3387 | 3410 |
3388 template <typename TraitsType> | 3411 template <typename TraitsType> |
3389 void AssemblerX86Base<TraitsType>::emitComplexI8(int rm, const Operand &operand, | 3412 void AssemblerX86Base<TraitsType>::emitComplexI8(int rm, const Operand &operand, |
3390 const Immediate &immediate) { | 3413 const Immediate &immediate) { |
3391 assert(rm >= 0 && rm < 8); | 3414 assert(rm >= 0 && rm < 8); |
3392 assert(immediate.is_int8()); | 3415 assert(immediate.is_int8()); |
3393 if (operand.IsRegister(Traits::Encoded_Reg_Accumulator)) { | 3416 if (operand.IsRegister(Traits::Encoded_Reg_Accumulator)) { |
3394 // Use short form if the destination is al. | 3417 // Use short form if the destination is al. |
3395 emitUint8(0x04 + (rm << 3)); | 3418 emitUint8(0x04 + (rm << 3)); |
3396 emitUint8(immediate.value() & 0xFF); | 3419 emitUint8(immediate.value() & 0xFF); |
3397 } else { | 3420 } else { |
3398 // Use sign-extended 8-bit immediate. | 3421 // Use sign-extended 8-bit immediate. |
3399 emitUint8(0x80); | 3422 emitUint8(0x80); |
3400 emitOperand(rm, operand); | 3423 static constexpr RelocOffsetT OffsetFromNextInstruction = 1; |
3424 emitOperand(rm, operand, OffsetFromNextInstruction); | |
3401 emitUint8(immediate.value() & 0xFF); | 3425 emitUint8(immediate.value() & 0xFF); |
3402 } | 3426 } |
3403 } | 3427 } |
3404 | 3428 |
3405 template <typename TraitsType> | 3429 template <typename TraitsType> |
3406 void AssemblerX86Base<TraitsType>::emitComplex(Type Ty, int rm, | 3430 void AssemblerX86Base<TraitsType>::emitComplex(Type Ty, int rm, |
3407 const Operand &operand, | 3431 const Operand &operand, |
3408 const Immediate &immediate) { | 3432 const Immediate &immediate) { |
3409 assert(rm >= 0 && rm < 8); | 3433 assert(rm >= 0 && rm < 8); |
3410 if (immediate.is_int8()) { | 3434 if (immediate.is_int8()) { |
3411 // Use sign-extended 8-bit immediate. | 3435 // Use sign-extended 8-bit immediate. |
3412 emitUint8(0x83); | 3436 emitUint8(0x83); |
3413 emitOperand(rm, operand); | 3437 static constexpr RelocOffsetT OffsetFromNextInstruction = 1; |
3438 emitOperand(rm, operand, OffsetFromNextInstruction); | |
3414 emitUint8(immediate.value() & 0xFF); | 3439 emitUint8(immediate.value() & 0xFF); |
3415 } else if (operand.IsRegister(Traits::Encoded_Reg_Accumulator)) { | 3440 } else if (operand.IsRegister(Traits::Encoded_Reg_Accumulator)) { |
3416 // Use short form if the destination is eax. | 3441 // Use short form if the destination is eax. |
3417 emitUint8(0x05 + (rm << 3)); | 3442 emitUint8(0x05 + (rm << 3)); |
3418 emitImmediate(Ty, immediate); | 3443 emitImmediate(Ty, immediate); |
3419 } else { | 3444 } else { |
3420 emitUint8(0x81); | 3445 emitUint8(0x81); |
3421 emitOperand(rm, operand); | 3446 const uint8_t OffsetFromNextInstruction = Ty == IceType_i16 ? 2 : 4; |
3447 emitOperand(rm, operand, OffsetFromNextInstruction); | |
3422 emitImmediate(Ty, immediate); | 3448 emitImmediate(Ty, immediate); |
3423 } | 3449 } |
3424 } | 3450 } |
3425 | 3451 |
3426 template <typename TraitsType> | 3452 template <typename TraitsType> |
3427 void AssemblerX86Base<TraitsType>::emitLabel(Label *label, | 3453 void AssemblerX86Base<TraitsType>::emitLabel(Label *label, |
3428 intptr_t instruction_size) { | 3454 intptr_t instruction_size) { |
3429 if (label->isBound()) { | 3455 if (label->isBound()) { |
3430 intptr_t offset = label->getPosition() - Buffer.size(); | 3456 intptr_t offset = label->getPosition() - Buffer.size(); |
3431 assert(offset <= 0); | 3457 assert(offset <= 0); |
(...skipping 29 matching lines...) Expand all Loading... | |
3461 // same processor behavior regardless of whether it's an immediate (masked to | 3487 // same processor behavior regardless of whether it's an immediate (masked to |
3462 // 8 bits) or in register cl (essentially ecx masked to 8 bits). | 3488 // 8 bits) or in register cl (essentially ecx masked to 8 bits). |
3463 if (Ty == IceType_i16) | 3489 if (Ty == IceType_i16) |
3464 emitOperandSizeOverride(); | 3490 emitOperandSizeOverride(); |
3465 emitRexB(Ty, reg); | 3491 emitRexB(Ty, reg); |
3466 if (imm.value() == 1) { | 3492 if (imm.value() == 1) { |
3467 emitUint8(isByteSizedArithType(Ty) ? 0xD0 : 0xD1); | 3493 emitUint8(isByteSizedArithType(Ty) ? 0xD0 : 0xD1); |
3468 emitOperand(rm, Operand(reg)); | 3494 emitOperand(rm, Operand(reg)); |
3469 } else { | 3495 } else { |
3470 emitUint8(isByteSizedArithType(Ty) ? 0xC0 : 0xC1); | 3496 emitUint8(isByteSizedArithType(Ty) ? 0xC0 : 0xC1); |
3471 emitOperand(rm, Operand(reg)); | 3497 static constexpr RelocOffsetT OffsetFromNextInstruction = 1; |
3498 emitOperand(rm, Operand(reg), OffsetFromNextInstruction); | |
3472 emitUint8(imm.value() & 0xFF); | 3499 emitUint8(imm.value() & 0xFF); |
3473 } | 3500 } |
3474 } | 3501 } |
3475 | 3502 |
3476 template <typename TraitsType> | 3503 template <typename TraitsType> |
3477 void AssemblerX86Base<TraitsType>::emitGenericShift(int rm, Type Ty, | 3504 void AssemblerX86Base<TraitsType>::emitGenericShift(int rm, Type Ty, |
3478 const Operand &operand, | 3505 const Operand &operand, |
3479 GPRRegister shifter) { | 3506 GPRRegister shifter) { |
3480 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 3507 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
3481 assert(shifter == Traits::Encoded_Reg_Counter); | 3508 assert(shifter == Traits::Encoded_Reg_Counter); |
3482 (void)shifter; | 3509 (void)shifter; |
3483 if (Ty == IceType_i16) | 3510 if (Ty == IceType_i16) |
3484 emitOperandSizeOverride(); | 3511 emitOperandSizeOverride(); |
3485 emitRexB(Ty, operand.rm()); | 3512 emitRexB(Ty, operand.rm()); |
3486 emitUint8(isByteSizedArithType(Ty) ? 0xD2 : 0xD3); | 3513 emitUint8(isByteSizedArithType(Ty) ? 0xD2 : 0xD3); |
3487 emitOperand(rm, operand); | 3514 emitOperand(rm, operand); |
3488 } | 3515 } |
3489 | 3516 |
3490 } // end of namespace X86NAMESPACE | 3517 } // end of namespace X86NAMESPACE |
3491 } // end of namespace Ice | 3518 } // end of namespace Ice |
OLD | NEW |