OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 690 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
701 last_pc_ = pc_; | 701 last_pc_ = pc_; |
702 emit_optional_rex_32(dst); | 702 emit_optional_rex_32(dst); |
703 emit(0xD3); | 703 emit(0xD3); |
704 emit_modrm(subcode, dst); | 704 emit_modrm(subcode, dst); |
705 } | 705 } |
706 | 706 |
707 | 707 |
708 void Assembler::shift_32(Register dst, Immediate shift_amount, int subcode) { | 708 void Assembler::shift_32(Register dst, Immediate shift_amount, int subcode) { |
709 EnsureSpace ensure_space(this); | 709 EnsureSpace ensure_space(this); |
710 last_pc_ = pc_; | 710 last_pc_ = pc_; |
711 ASSERT(is_uint6(shift_amount.value_)); // illegal shift count | 711 ASSERT(is_uint5(shift_amount.value_)); // illegal shift count |
712 if (shift_amount.value_ == 1) { | 712 if (shift_amount.value_ == 1) { |
713 emit_optional_rex_32(dst); | 713 emit_optional_rex_32(dst); |
714 emit(0xD1); | 714 emit(0xD1); |
715 emit_modrm(subcode, dst); | 715 emit_modrm(subcode, dst); |
716 } else { | 716 } else { |
717 emit_optional_rex_32(dst); | 717 emit_optional_rex_32(dst); |
718 emit(0xC1); | 718 emit(0xC1); |
719 emit_modrm(subcode, dst); | 719 emit_modrm(subcode, dst); |
720 emit(shift_amount.value_); | 720 emit(shift_amount.value_); |
721 } | 721 } |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
787 void Assembler::call(const Operand& op) { | 787 void Assembler::call(const Operand& op) { |
788 EnsureSpace ensure_space(this); | 788 EnsureSpace ensure_space(this); |
789 last_pc_ = pc_; | 789 last_pc_ = pc_; |
790 // Opcode: FF /2 m64 | 790 // Opcode: FF /2 m64 |
791 emit_rex_64(op); | 791 emit_rex_64(op); |
792 emit(0xFF); | 792 emit(0xFF); |
793 emit_operand(2, op); | 793 emit_operand(2, op); |
794 } | 794 } |
795 | 795 |
796 | 796 |
| 797 void Assembler::clc() { |
| 798 EnsureSpace ensure_space(this); |
| 799 last_pc_ = pc_; |
| 800 emit(0xF8); |
| 801 } |
| 802 |
797 void Assembler::cdq() { | 803 void Assembler::cdq() { |
798 EnsureSpace ensure_space(this); | 804 EnsureSpace ensure_space(this); |
799 last_pc_ = pc_; | 805 last_pc_ = pc_; |
800 emit(0x99); | 806 emit(0x99); |
801 } | 807 } |
802 | 808 |
803 | 809 |
804 void Assembler::cmovq(Condition cc, Register dst, Register src) { | 810 void Assembler::cmovq(Condition cc, Register dst, Register src) { |
| 811 if (cc == always) { |
| 812 movq(dst, src); |
| 813 } else if (cc == never) { |
| 814 return; |
| 815 } |
805 // No need to check CpuInfo for CMOV support, it's a required part of the | 816 // No need to check CpuInfo for CMOV support, it's a required part of the |
806 // 64-bit architecture. | 817 // 64-bit architecture. |
807 ASSERT(cc >= 0); // Use mov for unconditional moves. | 818 ASSERT(cc >= 0); // Use mov for unconditional moves. |
808 EnsureSpace ensure_space(this); | 819 EnsureSpace ensure_space(this); |
809 last_pc_ = pc_; | 820 last_pc_ = pc_; |
810 // Opcode: REX.W 0f 40 + cc /r | 821 // Opcode: REX.W 0f 40 + cc /r |
811 emit_rex_64(dst, src); | 822 emit_rex_64(dst, src); |
812 emit(0x0f); | 823 emit(0x0f); |
813 emit(0x40 + cc); | 824 emit(0x40 + cc); |
814 emit_modrm(dst, src); | 825 emit_modrm(dst, src); |
815 } | 826 } |
816 | 827 |
817 | 828 |
818 void Assembler::cmovq(Condition cc, Register dst, const Operand& src) { | 829 void Assembler::cmovq(Condition cc, Register dst, const Operand& src) { |
| 830 if (cc == always) { |
| 831 movq(dst, src); |
| 832 } else if (cc == never) { |
| 833 return; |
| 834 } |
819 ASSERT(cc >= 0); | 835 ASSERT(cc >= 0); |
820 EnsureSpace ensure_space(this); | 836 EnsureSpace ensure_space(this); |
821 last_pc_ = pc_; | 837 last_pc_ = pc_; |
822 // Opcode: REX.W 0f 40 + cc /r | 838 // Opcode: REX.W 0f 40 + cc /r |
823 emit_rex_64(dst, src); | 839 emit_rex_64(dst, src); |
824 emit(0x0f); | 840 emit(0x0f); |
825 emit(0x40 + cc); | 841 emit(0x40 + cc); |
826 emit_operand(dst, src); | 842 emit_operand(dst, src); |
827 } | 843 } |
828 | 844 |
829 | 845 |
830 void Assembler::cmovl(Condition cc, Register dst, Register src) { | 846 void Assembler::cmovl(Condition cc, Register dst, Register src) { |
| 847 if (cc == always) { |
| 848 movl(dst, src); |
| 849 } else if (cc == never) { |
| 850 return; |
| 851 } |
831 ASSERT(cc >= 0); | 852 ASSERT(cc >= 0); |
832 EnsureSpace ensure_space(this); | 853 EnsureSpace ensure_space(this); |
833 last_pc_ = pc_; | 854 last_pc_ = pc_; |
834 // Opcode: 0f 40 + cc /r | 855 // Opcode: 0f 40 + cc /r |
835 emit_optional_rex_32(dst, src); | 856 emit_optional_rex_32(dst, src); |
836 emit(0x0f); | 857 emit(0x0f); |
837 emit(0x40 + cc); | 858 emit(0x40 + cc); |
838 emit_modrm(dst, src); | 859 emit_modrm(dst, src); |
839 } | 860 } |
840 | 861 |
841 | 862 |
842 void Assembler::cmovl(Condition cc, Register dst, const Operand& src) { | 863 void Assembler::cmovl(Condition cc, Register dst, const Operand& src) { |
| 864 if (cc == always) { |
| 865 movl(dst, src); |
| 866 } else if (cc == never) { |
| 867 return; |
| 868 } |
843 ASSERT(cc >= 0); | 869 ASSERT(cc >= 0); |
844 EnsureSpace ensure_space(this); | 870 EnsureSpace ensure_space(this); |
845 last_pc_ = pc_; | 871 last_pc_ = pc_; |
846 // Opcode: 0f 40 + cc /r | 872 // Opcode: 0f 40 + cc /r |
847 emit_optional_rex_32(dst, src); | 873 emit_optional_rex_32(dst, src); |
848 emit(0x0f); | 874 emit(0x0f); |
849 emit(0x40 + cc); | 875 emit(0x40 + cc); |
850 emit_operand(dst, src); | 876 emit_operand(dst, src); |
851 } | 877 } |
852 | 878 |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1051 | 1077 |
1052 | 1078 |
1053 void Assembler::int3() { | 1079 void Assembler::int3() { |
1054 EnsureSpace ensure_space(this); | 1080 EnsureSpace ensure_space(this); |
1055 last_pc_ = pc_; | 1081 last_pc_ = pc_; |
1056 emit(0xCC); | 1082 emit(0xCC); |
1057 } | 1083 } |
1058 | 1084 |
1059 | 1085 |
1060 void Assembler::j(Condition cc, Label* L) { | 1086 void Assembler::j(Condition cc, Label* L) { |
| 1087 if (cc == always) { |
| 1088 jmp(L); |
| 1089 return; |
| 1090 } else if (cc == never) { |
| 1091 return; |
| 1092 } |
1061 EnsureSpace ensure_space(this); | 1093 EnsureSpace ensure_space(this); |
1062 last_pc_ = pc_; | 1094 last_pc_ = pc_; |
1063 ASSERT(is_uint4(cc)); | 1095 ASSERT(is_uint4(cc)); |
1064 if (L->is_bound()) { | 1096 if (L->is_bound()) { |
1065 const int short_size = 2; | 1097 const int short_size = 2; |
1066 const int long_size = 6; | 1098 const int long_size = 6; |
1067 int offs = L->pos() - pc_offset(); | 1099 int offs = L->pos() - pc_offset(); |
1068 ASSERT(offs <= 0); | 1100 ASSERT(offs <= 0); |
1069 if (is_int8(offs - short_size)) { | 1101 if (is_int8(offs - short_size)) { |
1070 // 0111 tttn #8-bit disp | 1102 // 0111 tttn #8-bit disp |
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1387 } | 1419 } |
1388 | 1420 |
1389 | 1421 |
1390 void Assembler::movq(Register dst, Handle<Object> value, RelocInfo::Mode mode) { | 1422 void Assembler::movq(Register dst, Handle<Object> value, RelocInfo::Mode mode) { |
1391 // If there is no relocation info, emit the value of the handle efficiently | 1423 // If there is no relocation info, emit the value of the handle efficiently |
1392 // (possibly using less that 8 bytes for the value). | 1424 // (possibly using less that 8 bytes for the value). |
1393 if (mode == RelocInfo::NONE) { | 1425 if (mode == RelocInfo::NONE) { |
1394 // There is no possible reason to store a heap pointer without relocation | 1426 // There is no possible reason to store a heap pointer without relocation |
1395 // info, so it must be a smi. | 1427 // info, so it must be a smi. |
1396 ASSERT(value->IsSmi()); | 1428 ASSERT(value->IsSmi()); |
1397 // Smis never have more than 32 significant bits, but they might | 1429 movq(dst, reinterpret_cast<int64_t>(*value), RelocInfo::NONE); |
1398 // have garbage in the high bits. | |
1399 movq(dst, | |
1400 Immediate(static_cast<int32_t>(reinterpret_cast<intptr_t>(*value)))); | |
1401 } else { | 1430 } else { |
1402 EnsureSpace ensure_space(this); | 1431 EnsureSpace ensure_space(this); |
1403 last_pc_ = pc_; | 1432 last_pc_ = pc_; |
1404 ASSERT(value->IsHeapObject()); | 1433 ASSERT(value->IsHeapObject()); |
1405 ASSERT(!Heap::InNewSpace(*value)); | 1434 ASSERT(!Heap::InNewSpace(*value)); |
1406 emit_rex_64(dst); | 1435 emit_rex_64(dst); |
1407 emit(0xB8 | dst.low_bits()); | 1436 emit(0xB8 | dst.low_bits()); |
1408 emitq(reinterpret_cast<uintptr_t>(value.location()), mode); | 1437 emitq(reinterpret_cast<uintptr_t>(value.location()), mode); |
1409 } | 1438 } |
1410 } | 1439 } |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1664 } | 1693 } |
1665 | 1694 |
1666 | 1695 |
1667 void Assembler::pushfq() { | 1696 void Assembler::pushfq() { |
1668 EnsureSpace ensure_space(this); | 1697 EnsureSpace ensure_space(this); |
1669 last_pc_ = pc_; | 1698 last_pc_ = pc_; |
1670 emit(0x9C); | 1699 emit(0x9C); |
1671 } | 1700 } |
1672 | 1701 |
1673 | 1702 |
1674 void Assembler::rcl(Register dst, uint8_t imm8) { | |
1675 EnsureSpace ensure_space(this); | |
1676 last_pc_ = pc_; | |
1677 ASSERT(is_uint6(imm8)); // illegal shift count | |
1678 if (imm8 == 1) { | |
1679 emit_rex_64(dst); | |
1680 emit(0xD1); | |
1681 emit_modrm(0x2, dst); | |
1682 } else { | |
1683 emit_rex_64(dst); | |
1684 emit(0xC1); | |
1685 emit_modrm(0x2, dst); | |
1686 emit(imm8); | |
1687 } | |
1688 } | |
1689 | |
1690 void Assembler::rdtsc() { | 1703 void Assembler::rdtsc() { |
1691 EnsureSpace ensure_space(this); | 1704 EnsureSpace ensure_space(this); |
1692 last_pc_ = pc_; | 1705 last_pc_ = pc_; |
1693 emit(0x0F); | 1706 emit(0x0F); |
1694 emit(0x31); | 1707 emit(0x31); |
1695 } | 1708 } |
1696 | 1709 |
1697 | 1710 |
1698 void Assembler::ret(int imm16) { | 1711 void Assembler::ret(int imm16) { |
1699 EnsureSpace ensure_space(this); | 1712 EnsureSpace ensure_space(this); |
1700 last_pc_ = pc_; | 1713 last_pc_ = pc_; |
1701 ASSERT(is_uint16(imm16)); | 1714 ASSERT(is_uint16(imm16)); |
1702 if (imm16 == 0) { | 1715 if (imm16 == 0) { |
1703 emit(0xC3); | 1716 emit(0xC3); |
1704 } else { | 1717 } else { |
1705 emit(0xC2); | 1718 emit(0xC2); |
1706 emit(imm16 & 0xFF); | 1719 emit(imm16 & 0xFF); |
1707 emit((imm16 >> 8) & 0xFF); | 1720 emit((imm16 >> 8) & 0xFF); |
1708 } | 1721 } |
1709 } | 1722 } |
1710 | 1723 |
1711 | 1724 |
1712 void Assembler::setcc(Condition cc, Register reg) { | 1725 void Assembler::setcc(Condition cc, Register reg) { |
| 1726 if (cc > last_condition) { |
| 1727 movb(reg, Immediate(cc == always ? 1 : 0)); |
| 1728 return; |
| 1729 } |
1713 EnsureSpace ensure_space(this); | 1730 EnsureSpace ensure_space(this); |
1714 last_pc_ = pc_; | 1731 last_pc_ = pc_; |
1715 ASSERT(is_uint4(cc)); | 1732 ASSERT(is_uint4(cc)); |
1716 if (reg.code() > 3) { // Use x64 byte registers, where different. | 1733 if (reg.code() > 3) { // Use x64 byte registers, where different. |
1717 emit_rex_32(reg); | 1734 emit_rex_32(reg); |
1718 } | 1735 } |
1719 emit(0x0F); | 1736 emit(0x0F); |
1720 emit(0x90 | cc); | 1737 emit(0x90 | cc); |
1721 emit_modrm(0x0, reg); | 1738 emit_modrm(0x0, reg); |
1722 } | 1739 } |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1764 emit(0xA3); | 1781 emit(0xA3); |
1765 emitq(reinterpret_cast<uintptr_t>(dst), mode); | 1782 emitq(reinterpret_cast<uintptr_t>(dst), mode); |
1766 } | 1783 } |
1767 | 1784 |
1768 | 1785 |
1769 void Assembler::store_rax(ExternalReference ref) { | 1786 void Assembler::store_rax(ExternalReference ref) { |
1770 store_rax(ref.address(), RelocInfo::EXTERNAL_REFERENCE); | 1787 store_rax(ref.address(), RelocInfo::EXTERNAL_REFERENCE); |
1771 } | 1788 } |
1772 | 1789 |
1773 | 1790 |
| 1791 void Assembler::testb(Register dst, Register src) { |
| 1792 EnsureSpace ensure_space(this); |
| 1793 last_pc_ = pc_; |
| 1794 if (dst.code() > 3 || src.code() > 3) { |
| 1795 // Register is not one of al, bl, cl, dl. Its encoding needs REX. |
| 1796 emit_rex_32(dst, src); |
| 1797 } |
| 1798 emit(0x84); |
| 1799 emit_modrm(dst, src); |
| 1800 } |
| 1801 |
| 1802 |
1774 void Assembler::testb(Register reg, Immediate mask) { | 1803 void Assembler::testb(Register reg, Immediate mask) { |
1775 ASSERT(is_int8(mask.value_) || is_uint8(mask.value_)); | 1804 ASSERT(is_int8(mask.value_) || is_uint8(mask.value_)); |
1776 EnsureSpace ensure_space(this); | 1805 EnsureSpace ensure_space(this); |
1777 last_pc_ = pc_; | 1806 last_pc_ = pc_; |
1778 if (reg.is(rax)) { | 1807 if (reg.is(rax)) { |
1779 emit(0xA8); | 1808 emit(0xA8); |
1780 emit(mask.value_); // Low byte emitted. | 1809 emit(mask.value_); // Low byte emitted. |
1781 } else { | 1810 } else { |
1782 if (reg.code() > 3) { | 1811 if (reg.code() > 3) { |
1783 // Register is not one of al, bl, cl, dl. Its encoding needs REX. | 1812 // Register is not one of al, bl, cl, dl. Its encoding needs REX. |
(...skipping 654 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2438 written_position_ = current_position_; | 2467 written_position_ = current_position_; |
2439 } | 2468 } |
2440 } | 2469 } |
2441 | 2470 |
2442 | 2471 |
2443 const int RelocInfo::kApplyMask = RelocInfo::kCodeTargetMask | | 2472 const int RelocInfo::kApplyMask = RelocInfo::kCodeTargetMask | |
2444 1 << RelocInfo::INTERNAL_REFERENCE | | 2473 1 << RelocInfo::INTERNAL_REFERENCE | |
2445 1 << RelocInfo::JS_RETURN; | 2474 1 << RelocInfo::JS_RETURN; |
2446 | 2475 |
2447 } } // namespace v8::internal | 2476 } } // namespace v8::internal |
OLD | NEW |