OLD | NEW |
---|---|
1 // Copyright (c) 1994-2006 Sun Microsystems Inc. | 1 // Copyright (c) 1994-2006 Sun Microsystems Inc. |
2 // All Rights Reserved. | 2 // All Rights Reserved. |
3 // | 3 // |
4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
6 // met: | 6 // met: |
7 // | 7 // |
8 // - Redistributions of source code must retain the above copyright notice, | 8 // - Redistributions of source code must retain the above copyright notice, |
9 // this list of conditions and the following disclaimer. | 9 // this list of conditions and the following disclaimer. |
10 // | 10 // |
(...skipping 491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
502 static uint64_t found_by_runtime_probing_only_; | 502 static uint64_t found_by_runtime_probing_only_; |
503 | 503 |
504 static uint64_t cross_compile_; | 504 static uint64_t cross_compile_; |
505 | 505 |
506 friend class ExternalReference; | 506 friend class ExternalReference; |
507 friend class PlatformFeatureScope; | 507 friend class PlatformFeatureScope; |
508 DISALLOW_COPY_AND_ASSIGN(CpuFeatures); | 508 DISALLOW_COPY_AND_ASSIGN(CpuFeatures); |
509 }; | 509 }; |
510 | 510 |
511 | 511 |
512 #define ASSEMBLER_INSTRUCTION_LIST(V) \ | 512 #define ASSEMBLER_INSTRUCTION_LIST(V) \ |
513 V(mov) | 513 V(add) \ |
514 V(idiv) \ | |
515 V(imul) \ | |
516 V(mov) \ | |
517 V(sub) | |
514 | 518 |
515 | 519 |
516 class Assembler : public AssemblerBase { | 520 class Assembler : public AssemblerBase { |
517 private: | 521 private: |
518 // We check before assembling an instruction that there is sufficient | 522 // We check before assembling an instruction that there is sufficient |
519 // space to write an instruction and its relocation information. | 523 // space to write an instruction and its relocation information. |
520 // The relocation writer's position must be kGap bytes above the end of | 524 // The relocation writer's position must be kGap bytes above the end of |
521 // the generated instructions. This leaves enough space for the | 525 // the generated instructions. This leaves enough space for the |
522 // longest possible x64 instruction, 15 bytes, and the longest possible | 526 // longest possible x64 instruction, 15 bytes, and the longest possible |
523 // relocation information encoding, RelocInfoWriter::kMaxLength == 16. | 527 // relocation information encoding, RelocInfoWriter::kMaxLength == 16. |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
657 // There are no versions of these instructions without the suffix. | 661 // There are no versions of these instructions without the suffix. |
658 // - Instructions on 8-bit (byte) operands/registers have a trailing 'b'. | 662 // - Instructions on 8-bit (byte) operands/registers have a trailing 'b'. |
659 // - Instructions on 16-bit (word) operands/registers have a trailing 'w'. | 663 // - Instructions on 16-bit (word) operands/registers have a trailing 'w'. |
660 // - Instructions on 32-bit (doubleword) operands/registers use 'l'. | 664 // - Instructions on 32-bit (doubleword) operands/registers use 'l'. |
661 // - Instructions on 64-bit (quadword) operands/registers use 'q'. | 665 // - Instructions on 64-bit (quadword) operands/registers use 'q'. |
662 // | 666 // |
663 // Some mnemonics, such as "and", are the same as C++ keywords. | 667 // Some mnemonics, such as "and", are the same as C++ keywords. |
664 // Naming conflicts with C++ keywords are resolved by adding a trailing '_'. | 668 // Naming conflicts with C++ keywords are resolved by adding a trailing '_'. |
665 | 669 |
666 #define DECLARE_INSTRUCTION(instruction) \ | 670 #define DECLARE_INSTRUCTION(instruction) \ |
671 template<class P1> \ | |
672 void instruction##p(P1 p1) { \ | |
673 emit_##instruction(p1, kPointerSize); \ | |
674 } \ | |
675 \ | |
676 template<class P1> \ | |
677 void instruction##l(P1 p1) { \ | |
678 emit_##instruction(p1, kInt32Size); \ | |
679 } \ | |
680 \ | |
681 template<class P1> \ | |
682 void instruction##q(P1 p1) { \ | |
683 emit_##instruction(p1, kInt64Size); \ | |
684 } \ | |
685 \ | |
667 template<class P1, class P2> \ | 686 template<class P1, class P2> \ |
668 void instruction##p(P1 p1, P2 p2) { \ | 687 void instruction##p(P1 p1, P2 p2) { \ |
669 emit_##instruction(p1, p2, kPointerSize); \ | 688 emit_##instruction(p1, p2, kPointerSize); \ |
670 } \ | 689 } \ |
671 \ | 690 \ |
672 template<class P1, class P2> \ | 691 template<class P1, class P2> \ |
673 void instruction##l(P1 p1, P2 p2) { \ | 692 void instruction##l(P1 p1, P2 p2) { \ |
674 emit_##instruction(p1, p2, kInt32Size); \ | 693 emit_##instruction(p1, p2, kInt32Size); \ |
675 } \ | 694 } \ |
676 \ | 695 \ |
677 template<class P1, class P2> \ | 696 template<class P1, class P2> \ |
678 void instruction##q(P1 p1, P2 p2) { \ | 697 void instruction##q(P1 p1, P2 p2) { \ |
679 emit_##instruction(p1, p2, kInt64Size); \ | 698 emit_##instruction(p1, p2, kInt64Size); \ |
699 } \ | |
700 \ | |
701 template<class P1, class P2, class P3> \ | |
702 void instruction##p(P1 p1, P2 p2, P3 p3) { \ | |
703 emit_##instruction(p1, p2, p3, kPointerSize); \ | |
704 } \ | |
705 \ | |
706 template<class P1, class P2, class P3> \ | |
707 void instruction##l(P1 p1, P2 p2, P3 p3) { \ | |
708 emit_##instruction(p1, p2, p3, kInt32Size); \ | |
709 } \ | |
710 \ | |
711 template<class P1, class P2, class P3> \ | |
712 void instruction##q(P1 p1, P2 p2, P3 p3) { \ | |
713 emit_##instruction(p1, p2, p3, kInt64Size); \ | |
680 } | 714 } |
681 ASSEMBLER_INSTRUCTION_LIST(DECLARE_INSTRUCTION) | 715 ASSEMBLER_INSTRUCTION_LIST(DECLARE_INSTRUCTION) |
682 #undef DECLARE_INSTRUCTION | 716 #undef DECLARE_INSTRUCTION |
683 | 717 |
684 // Insert the smallest number of nop instructions | 718 // Insert the smallest number of nop instructions |
685 // possible to align the pc offset to a multiple | 719 // possible to align the pc offset to a multiple |
686 // of m, where m must be a power of 2. | 720 // of m, where m must be a power of 2. |
687 void Align(int m); | 721 void Align(int m); |
688 void Nop(int bytes = 1); | 722 void Nop(int bytes = 1); |
689 // Aligns code to something that's optimal for a jump target for the platform. | 723 // Aligns code to something that's optimal for a jump target for the platform. |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
753 // Conditional moves. | 787 // Conditional moves. |
754 void cmovq(Condition cc, Register dst, Register src); | 788 void cmovq(Condition cc, Register dst, Register src); |
755 void cmovq(Condition cc, Register dst, const Operand& src); | 789 void cmovq(Condition cc, Register dst, const Operand& src); |
756 void cmovl(Condition cc, Register dst, Register src); | 790 void cmovl(Condition cc, Register dst, Register src); |
757 void cmovl(Condition cc, Register dst, const Operand& src); | 791 void cmovl(Condition cc, Register dst, const Operand& src); |
758 | 792 |
759 // Exchange two registers | 793 // Exchange two registers |
760 void xchgq(Register dst, Register src); | 794 void xchgq(Register dst, Register src); |
761 void xchgl(Register dst, Register src); | 795 void xchgl(Register dst, Register src); |
762 | 796 |
763 // Arithmetics | |
764 void addl(Register dst, Register src) { | |
765 arithmetic_op_32(0x03, dst, src); | |
766 } | |
767 | |
768 void addl(Register dst, Immediate src) { | |
769 immediate_arithmetic_op_32(0x0, dst, src); | |
770 } | |
771 | |
772 void addl(Register dst, const Operand& src) { | |
773 arithmetic_op_32(0x03, dst, src); | |
774 } | |
775 | |
776 void addl(const Operand& dst, Immediate src) { | |
777 immediate_arithmetic_op_32(0x0, dst, src); | |
778 } | |
779 | |
780 void addl(const Operand& dst, Register src) { | |
781 arithmetic_op_32(0x01, src, dst); | |
782 } | |
783 | |
784 void addq(Register dst, Register src) { | |
785 arithmetic_op(0x03, dst, src); | |
786 } | |
787 | |
788 void addq(Register dst, const Operand& src) { | |
789 arithmetic_op(0x03, dst, src); | |
790 } | |
791 | |
792 void addq(const Operand& dst, Register src) { | |
793 arithmetic_op(0x01, src, dst); | |
794 } | |
795 | |
796 void addq(Register dst, Immediate src) { | |
797 immediate_arithmetic_op(0x0, dst, src); | |
798 } | |
799 | |
800 void addq(const Operand& dst, Immediate src) { | |
801 immediate_arithmetic_op(0x0, dst, src); | |
802 } | |
803 | |
804 void sbbl(Register dst, Register src) { | 797 void sbbl(Register dst, Register src) { |
805 arithmetic_op_32(0x1b, dst, src); | 798 arithmetic_op_32(0x1b, dst, src); |
806 } | 799 } |
807 | 800 |
808 void sbbq(Register dst, Register src) { | 801 void sbbq(Register dst, Register src) { |
809 arithmetic_op(0x1b, dst, src); | 802 arithmetic_op(0x1b, dst, src); |
810 } | 803 } |
811 | 804 |
812 void cmpb(Register dst, Immediate src) { | 805 void cmpb(Register dst, Immediate src) { |
813 immediate_arithmetic_op_8(0x7, dst, src); | 806 immediate_arithmetic_op_8(0x7, dst, src); |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
932 void decl(Register dst); | 925 void decl(Register dst); |
933 void decl(const Operand& dst); | 926 void decl(const Operand& dst); |
934 void decb(Register dst); | 927 void decb(Register dst); |
935 void decb(const Operand& dst); | 928 void decb(const Operand& dst); |
936 | 929 |
937 // Sign-extends rax into rdx:rax. | 930 // Sign-extends rax into rdx:rax. |
938 void cqo(); | 931 void cqo(); |
939 // Sign-extends eax into edx:eax. | 932 // Sign-extends eax into edx:eax. |
940 void cdq(); | 933 void cdq(); |
941 | 934 |
942 // Divide rdx:rax by src. Quotient in rax, remainder in rdx. | |
943 void idivq(Register src); | |
944 // Divide edx:eax by lower 32 bits of src. Quotient in eax, rem. in edx. | |
945 void idivl(Register src); | |
946 | |
947 // Signed multiply instructions. | |
948 void imul(Register src); // rdx:rax = rax * src. | |
949 void imul(Register dst, Register src); // dst = dst * src. | |
950 void imul(Register dst, const Operand& src); // dst = dst * src. | |
951 void imul(Register dst, Register src, Immediate imm); // dst = src * imm. | |
952 // Signed 32-bit multiply instructions. | |
953 void imull(Register src); // edx:eax = eax * src. | |
954 void imull(Register dst, Register src); // dst = dst * src. | |
955 void imull(Register dst, const Operand& src); // dst = dst * src. | |
956 void imull(Register dst, Register src, Immediate imm); // dst = src * imm. | |
957 | |
958 void incq(Register dst); | 935 void incq(Register dst); |
959 void incq(const Operand& dst); | 936 void incq(const Operand& dst); |
960 void incl(Register dst); | 937 void incl(Register dst); |
961 void incl(const Operand& dst); | 938 void incl(const Operand& dst); |
962 | 939 |
963 void lea(Register dst, const Operand& src); | 940 void lea(Register dst, const Operand& src); |
964 void leal(Register dst, const Operand& src); | 941 void leal(Register dst, const Operand& src); |
965 | 942 |
966 // Multiply rax by src, put the result in rdx:rax. | 943 // Multiply rax by src, put the result in rdx:rax. |
967 void mul(Register src); | 944 void mul(Register src); |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1098 shift_32(dst, 0x5); | 1075 shift_32(dst, 0x5); |
1099 } | 1076 } |
1100 | 1077 |
1101 void shrl(Register dst, Immediate shift_amount) { | 1078 void shrl(Register dst, Immediate shift_amount) { |
1102 shift_32(dst, shift_amount, 0x5); | 1079 shift_32(dst, shift_amount, 0x5); |
1103 } | 1080 } |
1104 | 1081 |
1105 void store_rax(void* dst, RelocInfo::Mode mode); | 1082 void store_rax(void* dst, RelocInfo::Mode mode); |
1106 void store_rax(ExternalReference ref); | 1083 void store_rax(ExternalReference ref); |
1107 | 1084 |
1108 void subq(Register dst, Register src) { | |
1109 arithmetic_op(0x2B, dst, src); | |
1110 } | |
1111 | |
1112 void subq(Register dst, const Operand& src) { | |
1113 arithmetic_op(0x2B, dst, src); | |
1114 } | |
1115 | |
1116 void subq(const Operand& dst, Register src) { | |
1117 arithmetic_op(0x29, src, dst); | |
1118 } | |
1119 | |
1120 void subq(Register dst, Immediate src) { | |
1121 immediate_arithmetic_op(0x5, dst, src); | |
1122 } | |
1123 | |
1124 void subq(const Operand& dst, Immediate src) { | |
1125 immediate_arithmetic_op(0x5, dst, src); | |
1126 } | |
1127 | |
1128 void subl(Register dst, Register src) { | |
1129 arithmetic_op_32(0x2B, dst, src); | |
1130 } | |
1131 | |
1132 void subl(Register dst, const Operand& src) { | |
1133 arithmetic_op_32(0x2B, dst, src); | |
1134 } | |
1135 | |
1136 void subl(const Operand& dst, Register src) { | |
1137 arithmetic_op_32(0x29, src, dst); | |
1138 } | |
1139 | |
1140 void subl(const Operand& dst, Immediate src) { | |
1141 immediate_arithmetic_op_32(0x5, dst, src); | |
1142 } | |
1143 | |
1144 void subl(Register dst, Immediate src) { | |
1145 immediate_arithmetic_op_32(0x5, dst, src); | |
1146 } | |
1147 | |
1148 void subb(Register dst, Immediate src) { | 1085 void subb(Register dst, Immediate src) { |
1149 immediate_arithmetic_op_8(0x5, dst, src); | 1086 immediate_arithmetic_op_8(0x5, dst, src); |
1150 } | 1087 } |
1151 | 1088 |
1152 void testb(Register dst, Register src); | 1089 void testb(Register dst, Register src); |
1153 void testb(Register reg, Immediate mask); | 1090 void testb(Register reg, Immediate mask); |
1154 void testb(const Operand& op, Immediate mask); | 1091 void testb(const Operand& op, Immediate mask); |
1155 void testb(const Operand& op, Register reg); | 1092 void testb(const Operand& op, Register reg); |
1156 void testl(Register dst, Register src); | 1093 void testl(Register dst, Register src); |
1157 void testl(Register reg, Immediate mask); | 1094 void testl(Register reg, Immediate mask); |
(...skipping 547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1705 | 1642 |
1706 void emit_farith(int b1, int b2, int i); | 1643 void emit_farith(int b1, int b2, int i); |
1707 | 1644 |
1708 // labels | 1645 // labels |
1709 // void print(Label* L); | 1646 // void print(Label* L); |
1710 void bind_to(Label* L, int pos); | 1647 void bind_to(Label* L, int pos); |
1711 | 1648 |
1712 // record reloc info for current pc_ | 1649 // record reloc info for current pc_ |
1713 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0); | 1650 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0); |
1714 | 1651 |
1652 // Arithmetics | |
1653 void emit_add(Register dst, Register src, int size) { | |
1654 if (size == kInt64Size) { | |
1655 arithmetic_op(0x03, dst, src); | |
1656 } else { | |
1657 ASSERT(size == kInt32Size); | |
1658 arithmetic_op_32(0x03, dst, src); | |
haitao.feng
2014/03/19 15:21:25
The arithmetic_op and arithmetic_op_32 could be un
Toon Verwaest
2014/03/20 10:43:50
Sounds good.
On 2014/03/19 15:21:25, haitao.feng
| |
1659 } | |
1660 } | |
1661 | |
1662 void emit_add(Register dst, Immediate src, int size) { | |
1663 if (size == kInt64Size) { | |
1664 immediate_arithmetic_op(0x0, dst, src); | |
1665 } else { | |
1666 ASSERT(size == kInt32Size); | |
1667 immediate_arithmetic_op_32(0x0, dst, src); | |
1668 } | |
1669 } | |
1670 | |
1671 void emit_add(Register dst, const Operand& src, int size) { | |
1672 if (size == kInt64Size) { | |
1673 arithmetic_op(0x03, dst, src); | |
1674 } else { | |
1675 ASSERT(size == kInt32Size); | |
1676 arithmetic_op_32(0x03, dst, src); | |
1677 } | |
1678 } | |
1679 | |
1680 void emit_add(const Operand& dst, Register src, int size) { | |
1681 if (size == kInt64Size) { | |
1682 arithmetic_op(0x1, src, dst); | |
1683 } else { | |
1684 ASSERT(size == kInt32Size); | |
1685 arithmetic_op_32(0x1, src, dst); | |
1686 } | |
1687 } | |
1688 | |
1689 void emit_add(const Operand& dst, Immediate src, int size) { | |
1690 if (size == kInt64Size) { | |
1691 immediate_arithmetic_op(0x0, dst, src); | |
1692 } else { | |
1693 ASSERT(size == kInt32Size); | |
1694 immediate_arithmetic_op_32(0x0, dst, src); | |
1695 } | |
1696 } | |
1697 | |
1698 // Divide rdx:rax by src. Quotient in rax, remainder in rdx when size is 64. | |
1699 // Divide edx:eax by lower 32 bits of src. Quotient in eax, remainder in edx | |
1700 // when size is 32. | |
1701 void emit_idiv(Register src, int size); | |
1702 | |
1703 // Signed multiply instructions. | |
1704 // rdx:rax = rax * src when size is 64 or edx:eax = eax * src when size is 32. | |
1705 void emit_imul(Register src, int size); | |
1706 void emit_imul(Register dst, Register src, int size); | |
1707 void emit_imul(Register dst, const Operand& src, int size); | |
1708 void emit_imul(Register dst, Register src, Immediate imm, int size); | |
1709 | |
1710 void emit_sub(Register dst, Register src, int size) { | |
1711 if (size == kInt64Size) { | |
1712 arithmetic_op(0x2B, dst, src); | |
1713 } else { | |
1714 ASSERT(size == kInt32Size); | |
1715 arithmetic_op_32(0x2B, dst, src); | |
1716 } | |
1717 } | |
1718 | |
1719 void emit_sub(Register dst, Immediate src, int size) { | |
1720 if (size == kInt64Size) { | |
1721 immediate_arithmetic_op(0x5, dst, src); | |
1722 } else { | |
1723 ASSERT(size == kInt32Size); | |
1724 immediate_arithmetic_op_32(0x5, dst, src); | |
1725 } | |
1726 } | |
1727 | |
1728 void emit_sub(Register dst, const Operand& src, int size) { | |
1729 if (size == kInt64Size) { | |
1730 arithmetic_op(0x2B, dst, src); | |
1731 } else { | |
1732 ASSERT(size == kInt32Size); | |
1733 arithmetic_op_32(0x2B, dst, src); | |
1734 } | |
1735 } | |
1736 | |
1737 void emit_sub(const Operand& dst, Register src, int size) { | |
1738 if (size == kInt64Size) { | |
1739 arithmetic_op(0x29, src, dst); | |
1740 } else { | |
1741 ASSERT(size == kInt32Size); | |
1742 arithmetic_op_32(0x29, src, dst); | |
1743 } | |
1744 } | |
1745 | |
1746 void emit_sub(const Operand& dst, Immediate src, int size) { | |
1747 if (size == kInt64Size) { | |
1748 immediate_arithmetic_op(0x5, dst, src); | |
1749 } else { | |
1750 ASSERT(size == kInt32Size); | |
1751 immediate_arithmetic_op_32(0x5, dst, src); | |
1752 } | |
1753 } | |
1754 | |
1715 void emit_mov(Register dst, const Operand& src, int size); | 1755 void emit_mov(Register dst, const Operand& src, int size); |
1716 void emit_mov(Register dst, Register src, int size); | 1756 void emit_mov(Register dst, Register src, int size); |
1717 void emit_mov(const Operand& dst, Register src, int size); | 1757 void emit_mov(const Operand& dst, Register src, int size); |
1718 void emit_mov(Register dst, Immediate value, int size); | 1758 void emit_mov(Register dst, Immediate value, int size); |
1719 void emit_mov(const Operand& dst, Immediate value, int size); | 1759 void emit_mov(const Operand& dst, Immediate value, int size); |
1720 | 1760 |
1721 friend class CodePatcher; | 1761 friend class CodePatcher; |
1722 friend class EnsureSpace; | 1762 friend class EnsureSpace; |
1723 friend class RegExpMacroAssemblerX64; | 1763 friend class RegExpMacroAssemblerX64; |
1724 | 1764 |
(...skipping 30 matching lines...) Expand all Loading... | |
1755 private: | 1795 private: |
1756 Assembler* assembler_; | 1796 Assembler* assembler_; |
1757 #ifdef DEBUG | 1797 #ifdef DEBUG |
1758 int space_before_; | 1798 int space_before_; |
1759 #endif | 1799 #endif |
1760 }; | 1800 }; |
1761 | 1801 |
1762 } } // namespace v8::internal | 1802 } } // namespace v8::internal |
1763 | 1803 |
1764 #endif // V8_X64_ASSEMBLER_X64_H_ | 1804 #endif // V8_X64_ASSEMBLER_X64_H_ |
OLD | NEW |