| 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 553 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 564 // Should equal Debug::kX64JSReturnSequenceLength - kCallTargetAddressOffset; | 564 // Should equal Debug::kX64JSReturnSequenceLength - kCallTargetAddressOffset; |
| 565 static const int kPatchReturnSequenceAddressOffset = 13 - 4; | 565 static const int kPatchReturnSequenceAddressOffset = 13 - 4; |
| 566 // Distance between start of patched debug break slot and where the | 566 // Distance between start of patched debug break slot and where the |
| 567 // 32-bit displacement of a near call would be, relative to the pushed | 567 // 32-bit displacement of a near call would be, relative to the pushed |
| 568 // return address. TODO: Use return sequence length instead. | 568 // return address. TODO: Use return sequence length instead. |
| 569 // Should equal Debug::kX64JSReturnSequenceLength - kCallTargetAddressOffset; | 569 // Should equal Debug::kX64JSReturnSequenceLength - kCallTargetAddressOffset; |
| 570 static const int kPatchDebugBreakSlotAddressOffset = 13 - 4; | 570 static const int kPatchDebugBreakSlotAddressOffset = 13 - 4; |
| 571 // TODO(X64): Rename this, removing the "Real", after changing the above. | 571 // TODO(X64): Rename this, removing the "Real", after changing the above. |
| 572 static const int kRealPatchReturnSequenceAddressOffset = 2; | 572 static const int kRealPatchReturnSequenceAddressOffset = 2; |
| 573 | 573 |
| 574 // The x64 JS return sequence is padded with int3 to make it large | 574 // Some x64 JS code is padded with int3 to make it large |
| 575 // enough to hold a call instruction when the debugger patches it. | 575 // enough to hold an instruction when the debugger patches it. |
| 576 static const int kJumpInstructionLength = 13; |
| 576 static const int kCallInstructionLength = 13; | 577 static const int kCallInstructionLength = 13; |
| 577 static const int kJSReturnSequenceLength = 13; | 578 static const int kJSReturnSequenceLength = 13; |
| 579 static const int kShortCallInstructionLength = 5; |
| 578 | 580 |
| 579 // The debug break slot must be able to contain a call instruction. | 581 // The debug break slot must be able to contain a call instruction. |
| 580 static const int kDebugBreakSlotLength = kCallInstructionLength; | 582 static const int kDebugBreakSlotLength = kCallInstructionLength; |
| 581 | 583 |
| 582 // One byte opcode for test eax,0xXXXXXXXX. | 584 // One byte opcode for test eax,0xXXXXXXXX. |
| 583 static const byte kTestEaxByte = 0xA9; | 585 static const byte kTestEaxByte = 0xA9; |
| 586 // One byte opcode for test al, 0xXX. |
| 587 static const byte kTestAlByte = 0xA8; |
| 584 | 588 |
| 585 // --------------------------------------------------------------------------- | 589 // --------------------------------------------------------------------------- |
| 586 // Code generation | 590 // Code generation |
| 587 // | 591 // |
| 588 // Function names correspond one-to-one to x64 instruction mnemonics. | 592 // Function names correspond one-to-one to x64 instruction mnemonics. |
| 589 // Unless specified otherwise, instructions operate on 64-bit operands. | 593 // Unless specified otherwise, instructions operate on 64-bit operands. |
| 590 // | 594 // |
| 591 // If we need versions of an assembly instruction that operate on different | 595 // If we need versions of an assembly instruction that operate on different |
| 592 // width arguments, we add a single-letter suffix specifying the width. | 596 // width arguments, we add a single-letter suffix specifying the width. |
| 593 // This is done for the following instructions: mov, cmp, inc, dec, | 597 // This is done for the following instructions: mov, cmp, inc, dec, |
| 594 // add, sub, and test. | 598 // add, sub, and test. |
| 595 // There are no versions of these instructions without the suffix. | 599 // There are no versions of these instructions without the suffix. |
| 596 // - Instructions on 8-bit (byte) operands/registers have a trailing 'b'. | 600 // - Instructions on 8-bit (byte) operands/registers have a trailing 'b'. |
| 597 // - Instructions on 16-bit (word) operands/registers have a trailing 'w'. | 601 // - Instructions on 16-bit (word) operands/registers have a trailing 'w'. |
| 598 // - Instructions on 32-bit (doubleword) operands/registers use 'l'. | 602 // - Instructions on 32-bit (doubleword) operands/registers use 'l'. |
| 599 // - Instructions on 64-bit (quadword) operands/registers use 'q'. | 603 // - Instructions on 64-bit (quadword) operands/registers use 'q'. |
| 600 // | 604 // |
| 601 // Some mnemonics, such as "and", are the same as C++ keywords. | 605 // Some mnemonics, such as "and", are the same as C++ keywords. |
| 602 // Naming conflicts with C++ keywords are resolved by adding a trailing '_'. | 606 // Naming conflicts with C++ keywords are resolved by adding a trailing '_'. |
| 603 | 607 |
| 604 // Insert the smallest number of nop instructions | 608 // Insert the smallest number of nop instructions |
| 605 // possible to align the pc offset to a multiple | 609 // possible to align the pc offset to a multiple |
| 606 // of m. m must be a power of 2. | 610 // of m, where m must be a power of 2. |
| 607 void Align(int m); | 611 void Align(int m); |
| 608 // Aligns code to something that's optimal for a jump target for the platform. | 612 // Aligns code to something that's optimal for a jump target for the platform. |
| 609 void CodeTargetAlign(); | 613 void CodeTargetAlign(); |
| 610 | 614 |
| 611 // Stack | 615 // Stack |
| 612 void pushfq(); | 616 void pushfq(); |
| 613 void popfq(); | 617 void popfq(); |
| 614 | 618 |
| 615 void push(Immediate value); | 619 void push(Immediate value); |
| 616 // Push a 32 bit integer, and guarantee that it is actually pushed as a | 620 // Push a 32 bit integer, and guarantee that it is actually pushed as a |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 872 // Divide edx:eax by lower 32 bits of src. Quotient in eax, rem. in edx. | 876 // Divide edx:eax by lower 32 bits of src. Quotient in eax, rem. in edx. |
| 873 void idivl(Register src); | 877 void idivl(Register src); |
| 874 | 878 |
| 875 // Signed multiply instructions. | 879 // Signed multiply instructions. |
| 876 void imul(Register src); // rdx:rax = rax * src. | 880 void imul(Register src); // rdx:rax = rax * src. |
| 877 void imul(Register dst, Register src); // dst = dst * src. | 881 void imul(Register dst, Register src); // dst = dst * src. |
| 878 void imul(Register dst, const Operand& src); // dst = dst * src. | 882 void imul(Register dst, const Operand& src); // dst = dst * src. |
| 879 void imul(Register dst, Register src, Immediate imm); // dst = src * imm. | 883 void imul(Register dst, Register src, Immediate imm); // dst = src * imm. |
| 880 // Signed 32-bit multiply instructions. | 884 // Signed 32-bit multiply instructions. |
| 881 void imull(Register dst, Register src); // dst = dst * src. | 885 void imull(Register dst, Register src); // dst = dst * src. |
| 886 void imull(Register dst, const Operand& src); // dst = dst * src. |
| 882 void imull(Register dst, Register src, Immediate imm); // dst = src * imm. | 887 void imull(Register dst, Register src, Immediate imm); // dst = src * imm. |
| 883 | 888 |
| 884 void incq(Register dst); | 889 void incq(Register dst); |
| 885 void incq(const Operand& dst); | 890 void incq(const Operand& dst); |
| 886 void incl(Register dst); | 891 void incl(Register dst); |
| 887 void incl(const Operand& dst); | 892 void incl(const Operand& dst); |
| 888 | 893 |
| 889 void lea(Register dst, const Operand& src); | 894 void lea(Register dst, const Operand& src); |
| 890 void leal(Register dst, const Operand& src); | 895 void leal(Register dst, const Operand& src); |
| 891 | 896 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 905 } | 910 } |
| 906 | 911 |
| 907 void orl(Register dst, Register src) { | 912 void orl(Register dst, Register src) { |
| 908 arithmetic_op_32(0x0B, dst, src); | 913 arithmetic_op_32(0x0B, dst, src); |
| 909 } | 914 } |
| 910 | 915 |
| 911 void or_(Register dst, const Operand& src) { | 916 void or_(Register dst, const Operand& src) { |
| 912 arithmetic_op(0x0B, dst, src); | 917 arithmetic_op(0x0B, dst, src); |
| 913 } | 918 } |
| 914 | 919 |
| 920 void orl(Register dst, const Operand& src) { |
| 921 arithmetic_op_32(0x0B, dst, src); |
| 922 } |
| 923 |
| 915 void or_(const Operand& dst, Register src) { | 924 void or_(const Operand& dst, Register src) { |
| 916 arithmetic_op(0x09, src, dst); | 925 arithmetic_op(0x09, src, dst); |
| 917 } | 926 } |
| 918 | 927 |
| 919 void or_(Register dst, Immediate src) { | 928 void or_(Register dst, Immediate src) { |
| 920 immediate_arithmetic_op(0x1, dst, src); | 929 immediate_arithmetic_op(0x1, dst, src); |
| 921 } | 930 } |
| 922 | 931 |
| 923 void orl(Register dst, Immediate src) { | 932 void orl(Register dst, Immediate src) { |
| 924 immediate_arithmetic_op_32(0x1, dst, src); | 933 immediate_arithmetic_op_32(0x1, dst, src); |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1068 arithmetic_op_32(0x33, dst, src); | 1077 arithmetic_op_32(0x33, dst, src); |
| 1069 } else { | 1078 } else { |
| 1070 arithmetic_op(0x33, dst, src); | 1079 arithmetic_op(0x33, dst, src); |
| 1071 } | 1080 } |
| 1072 } | 1081 } |
| 1073 | 1082 |
| 1074 void xorl(Register dst, Register src) { | 1083 void xorl(Register dst, Register src) { |
| 1075 arithmetic_op_32(0x33, dst, src); | 1084 arithmetic_op_32(0x33, dst, src); |
| 1076 } | 1085 } |
| 1077 | 1086 |
| 1087 void xorl(Register dst, const Operand& src) { |
| 1088 arithmetic_op_32(0x33, dst, src); |
| 1089 } |
| 1090 |
| 1091 void xorl(Register dst, Immediate src) { |
| 1092 immediate_arithmetic_op_32(0x6, dst, src); |
| 1093 } |
| 1094 |
| 1095 void xorl(const Operand& dst, Immediate src) { |
| 1096 immediate_arithmetic_op_32(0x6, dst, src); |
| 1097 } |
| 1098 |
| 1078 void xor_(Register dst, const Operand& src) { | 1099 void xor_(Register dst, const Operand& src) { |
| 1079 arithmetic_op(0x33, dst, src); | 1100 arithmetic_op(0x33, dst, src); |
| 1080 } | 1101 } |
| 1081 | 1102 |
| 1082 void xor_(const Operand& dst, Register src) { | 1103 void xor_(const Operand& dst, Register src) { |
| 1083 arithmetic_op(0x31, src, dst); | 1104 arithmetic_op(0x31, src, dst); |
| 1084 } | 1105 } |
| 1085 | 1106 |
| 1086 void xor_(Register dst, Immediate src) { | 1107 void xor_(Register dst, Immediate src) { |
| 1087 immediate_arithmetic_op(0x6, dst, src); | 1108 immediate_arithmetic_op(0x6, dst, src); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1122 // but it may be bound only once. | 1143 // but it may be bound only once. |
| 1123 | 1144 |
| 1124 void bind(Label* L); // binds an unbound label L to the current code position | 1145 void bind(Label* L); // binds an unbound label L to the current code position |
| 1125 void bind(NearLabel* L); | 1146 void bind(NearLabel* L); |
| 1126 | 1147 |
| 1127 // Calls | 1148 // Calls |
| 1128 // Call near relative 32-bit displacement, relative to next instruction. | 1149 // Call near relative 32-bit displacement, relative to next instruction. |
| 1129 void call(Label* L); | 1150 void call(Label* L); |
| 1130 void call(Handle<Code> target, RelocInfo::Mode rmode); | 1151 void call(Handle<Code> target, RelocInfo::Mode rmode); |
| 1131 | 1152 |
| 1153 // Calls directly to the given address using a relative offset. |
| 1154 // Should only ever be used in Code objects for calls within the |
| 1155 // same Code object. Should not be used when generating new code (use labels), |
| 1156 // but only when patching existing code. |
| 1157 void call(Address target); |
| 1158 |
| 1132 // Call near absolute indirect, address in register | 1159 // Call near absolute indirect, address in register |
| 1133 void call(Register adr); | 1160 void call(Register adr); |
| 1134 | 1161 |
| 1135 // Call near indirect | 1162 // Call near indirect |
| 1136 void call(const Operand& operand); | 1163 void call(const Operand& operand); |
| 1137 | 1164 |
| 1138 // Jumps | 1165 // Jumps |
| 1139 // Jump short or near relative. | 1166 // Jump short or near relative. |
| 1140 // Use a 32-bit signed displacement. | 1167 // Use a 32-bit signed displacement. |
| 1141 void jmp(Label* L); // unconditional jump to L | 1168 void jmp(Label* L); // unconditional jump to L |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1265 void subsd(XMMRegister dst, XMMRegister src); | 1292 void subsd(XMMRegister dst, XMMRegister src); |
| 1266 void mulsd(XMMRegister dst, XMMRegister src); | 1293 void mulsd(XMMRegister dst, XMMRegister src); |
| 1267 void divsd(XMMRegister dst, XMMRegister src); | 1294 void divsd(XMMRegister dst, XMMRegister src); |
| 1268 | 1295 |
| 1269 void xorpd(XMMRegister dst, XMMRegister src); | 1296 void xorpd(XMMRegister dst, XMMRegister src); |
| 1270 void sqrtsd(XMMRegister dst, XMMRegister src); | 1297 void sqrtsd(XMMRegister dst, XMMRegister src); |
| 1271 | 1298 |
| 1272 void ucomisd(XMMRegister dst, XMMRegister src); | 1299 void ucomisd(XMMRegister dst, XMMRegister src); |
| 1273 void ucomisd(XMMRegister dst, const Operand& src); | 1300 void ucomisd(XMMRegister dst, const Operand& src); |
| 1274 | 1301 |
| 1302 void movmskpd(Register dst, XMMRegister src); |
| 1303 |
| 1275 // The first argument is the reg field, the second argument is the r/m field. | 1304 // The first argument is the reg field, the second argument is the r/m field. |
| 1276 void emit_sse_operand(XMMRegister dst, XMMRegister src); | 1305 void emit_sse_operand(XMMRegister dst, XMMRegister src); |
| 1277 void emit_sse_operand(XMMRegister reg, const Operand& adr); | 1306 void emit_sse_operand(XMMRegister reg, const Operand& adr); |
| 1278 void emit_sse_operand(XMMRegister dst, Register src); | 1307 void emit_sse_operand(XMMRegister dst, Register src); |
| 1279 void emit_sse_operand(Register dst, XMMRegister src); | 1308 void emit_sse_operand(Register dst, XMMRegister src); |
| 1280 | 1309 |
| 1281 // Debugging | 1310 // Debugging |
| 1282 void Print(); | 1311 void Print(); |
| 1283 | 1312 |
| 1284 // Check the code size generated from label to here. | 1313 // Check the code size generated from label to here. |
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1551 private: | 1580 private: |
| 1552 Assembler* assembler_; | 1581 Assembler* assembler_; |
| 1553 #ifdef DEBUG | 1582 #ifdef DEBUG |
| 1554 int space_before_; | 1583 int space_before_; |
| 1555 #endif | 1584 #endif |
| 1556 }; | 1585 }; |
| 1557 | 1586 |
| 1558 } } // namespace v8::internal | 1587 } } // namespace v8::internal |
| 1559 | 1588 |
| 1560 #endif // V8_X64_ASSEMBLER_X64_H_ | 1589 #endif // V8_X64_ASSEMBLER_X64_H_ |
| OLD | NEW |