| 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 26 matching lines...) Expand all Loading... |
| 37 #ifndef V8_X64_ASSEMBLER_X64_H_ | 37 #ifndef V8_X64_ASSEMBLER_X64_H_ |
| 38 #define V8_X64_ASSEMBLER_X64_H_ | 38 #define V8_X64_ASSEMBLER_X64_H_ |
| 39 | 39 |
| 40 #include "serialize.h" | 40 #include "serialize.h" |
| 41 | 41 |
| 42 namespace v8 { | 42 namespace v8 { |
| 43 namespace internal { | 43 namespace internal { |
| 44 | 44 |
| 45 // Utility functions | 45 // Utility functions |
| 46 | 46 |
| 47 // Test whether a 64-bit value is in a specific range. | |
| 48 inline bool is_uint32(int64_t x) { | |
| 49 static const uint64_t kMaxUInt32 = V8_UINT64_C(0xffffffff); | |
| 50 return static_cast<uint64_t>(x) <= kMaxUInt32; | |
| 51 } | |
| 52 | |
| 53 inline bool is_int32(int64_t x) { | |
| 54 static const int64_t kMinInt32 = -V8_INT64_C(0x80000000); | |
| 55 return is_uint32(x - kMinInt32); | |
| 56 } | |
| 57 | |
| 58 inline bool uint_is_int32(uint64_t x) { | |
| 59 static const uint64_t kMaxInt32 = V8_UINT64_C(0x7fffffff); | |
| 60 return x <= kMaxInt32; | |
| 61 } | |
| 62 | |
| 63 inline bool is_uint32(uint64_t x) { | |
| 64 static const uint64_t kMaxUInt32 = V8_UINT64_C(0xffffffff); | |
| 65 return x <= kMaxUInt32; | |
| 66 } | |
| 67 | |
| 68 // CPU Registers. | 47 // CPU Registers. |
| 69 // | 48 // |
| 70 // 1) We would prefer to use an enum, but enum values are assignment- | 49 // 1) We would prefer to use an enum, but enum values are assignment- |
| 71 // compatible with int, which has caused code-generation bugs. | 50 // compatible with int, which has caused code-generation bugs. |
| 72 // | 51 // |
| 73 // 2) We would prefer to use a class instead of a struct but we don't like | 52 // 2) We would prefer to use a class instead of a struct but we don't like |
| 74 // the register initialization to depend on the particular initialization | 53 // the register initialization to depend on the particular initialization |
| 75 // order (which appears to be different on OS X, Linux, and Windows for the | 54 // order (which appears to be different on OS X, Linux, and Windows for the |
| 76 // installed versions of C++ we tried). Using a struct permits C-style | 55 // installed versions of C++ we tried). Using a struct permits C-style |
| 77 // "initialization". Also, the Register objects cannot be const as this | 56 // "initialization". Also, the Register objects cannot be const as this |
| (...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 388 | 367 |
| 389 // ----------------------------------------------------------------------------- | 368 // ----------------------------------------------------------------------------- |
| 390 // Machine instruction Operands | 369 // Machine instruction Operands |
| 391 | 370 |
| 392 enum ScaleFactor { | 371 enum ScaleFactor { |
| 393 times_1 = 0, | 372 times_1 = 0, |
| 394 times_2 = 1, | 373 times_2 = 1, |
| 395 times_4 = 2, | 374 times_4 = 2, |
| 396 times_8 = 3, | 375 times_8 = 3, |
| 397 times_int_size = times_4, | 376 times_int_size = times_4, |
| 398 times_pointer_size = times_8 | 377 times_pointer_size = (kPointerSize == 8) ? times_8 : times_4 |
| 399 }; | 378 }; |
| 400 | 379 |
| 401 | 380 |
| 402 class Operand BASE_EMBEDDED { | 381 class Operand BASE_EMBEDDED { |
| 403 public: | 382 public: |
| 404 // [base + disp/r] | 383 // [base + disp/r] |
| 405 Operand(Register base, int32_t disp); | 384 Operand(Register base, int32_t disp); |
| 406 | 385 |
| 407 // [base + index*scale + disp/r] | 386 // [base + index*scale + disp/r] |
| 408 Operand(Register base, | 387 Operand(Register base, |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 583 // of that call in the instruction stream. | 562 // of that call in the instruction stream. |
| 584 static inline Address target_address_from_return_address(Address pc); | 563 static inline Address target_address_from_return_address(Address pc); |
| 585 | 564 |
| 586 // This sets the branch destination (which is in the instruction on x64). | 565 // This sets the branch destination (which is in the instruction on x64). |
| 587 // This is for calls and branches within generated code. | 566 // This is for calls and branches within generated code. |
| 588 inline static void deserialization_set_special_target_at( | 567 inline static void deserialization_set_special_target_at( |
| 589 Address instruction_payload, Address target) { | 568 Address instruction_payload, Address target) { |
| 590 set_target_address_at(instruction_payload, target); | 569 set_target_address_at(instruction_payload, target); |
| 591 } | 570 } |
| 592 | 571 |
| 572 static inline RelocInfo::Mode RelocInfoNone() { |
| 573 if (kPointerSize == kInt64Size) { |
| 574 return RelocInfo::NONE64; |
| 575 } else { |
| 576 ASSERT(kPointerSize == kInt32Size); |
| 577 return RelocInfo::NONE32; |
| 578 } |
| 579 } |
| 580 |
| 593 inline Handle<Object> code_target_object_handle_at(Address pc); | 581 inline Handle<Object> code_target_object_handle_at(Address pc); |
| 594 inline Address runtime_entry_at(Address pc); | 582 inline Address runtime_entry_at(Address pc); |
| 595 // Number of bytes taken up by the branch target in the code. | 583 // Number of bytes taken up by the branch target in the code. |
| 596 static const int kSpecialTargetSize = 4; // Use 32-bit displacement. | 584 static const int kSpecialTargetSize = 4; // Use 32-bit displacement. |
| 597 // Distance between the address of the code target in the call instruction | 585 // Distance between the address of the code target in the call instruction |
| 598 // and the return address pushed on the stack. | 586 // and the return address pushed on the stack. |
| 599 static const int kCallTargetAddressOffset = 4; // Use 32-bit displacement. | 587 static const int kCallTargetAddressOffset = 4; // Use 32-bit displacement. |
| 600 // The length of call(kScratchRegister). | 588 // The length of call(kScratchRegister). |
| 601 static const int kCallScratchRegisterInstructionLength = 3; | 589 static const int kCallScratchRegisterInstructionLength = 3; |
| 602 // The length of call(Immediate32). | 590 // The length of call(Immediate32). |
| (...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1005 } | 993 } |
| 1006 | 994 |
| 1007 void or_(const Operand& dst, Immediate src) { | 995 void or_(const Operand& dst, Immediate src) { |
| 1008 immediate_arithmetic_op(0x1, dst, src); | 996 immediate_arithmetic_op(0x1, dst, src); |
| 1009 } | 997 } |
| 1010 | 998 |
| 1011 void orl(const Operand& dst, Immediate src) { | 999 void orl(const Operand& dst, Immediate src) { |
| 1012 immediate_arithmetic_op_32(0x1, dst, src); | 1000 immediate_arithmetic_op_32(0x1, dst, src); |
| 1013 } | 1001 } |
| 1014 | 1002 |
| 1015 | |
| 1016 void rcl(Register dst, Immediate imm8) { | 1003 void rcl(Register dst, Immediate imm8) { |
| 1017 shift(dst, imm8, 0x2); | 1004 shift(dst, imm8, 0x2); |
| 1018 } | 1005 } |
| 1019 | 1006 |
| 1020 void rol(Register dst, Immediate imm8) { | 1007 void rol(Register dst, Immediate imm8) { |
| 1021 shift(dst, imm8, 0x0); | 1008 shift(dst, imm8, 0x0); |
| 1022 } | 1009 } |
| 1023 | 1010 |
| 1024 void roll(Register dst, Immediate imm8) { | 1011 void roll(Register dst, Immediate imm8) { |
| 1025 shift_32(dst, imm8, 0x0); | 1012 shift_32(dst, imm8, 0x0); |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1200 immediate_arithmetic_op(0x6, dst, src); | 1187 immediate_arithmetic_op(0x6, dst, src); |
| 1201 } | 1188 } |
| 1202 | 1189 |
| 1203 void xor_(const Operand& dst, Immediate src) { | 1190 void xor_(const Operand& dst, Immediate src) { |
| 1204 immediate_arithmetic_op(0x6, dst, src); | 1191 immediate_arithmetic_op(0x6, dst, src); |
| 1205 } | 1192 } |
| 1206 | 1193 |
| 1207 // Bit operations. | 1194 // Bit operations. |
| 1208 void bt(const Operand& dst, Register src); | 1195 void bt(const Operand& dst, Register src); |
| 1209 void bts(const Operand& dst, Register src); | 1196 void bts(const Operand& dst, Register src); |
| 1197 void bsrl(Register dst, Register src); |
| 1210 | 1198 |
| 1211 // Miscellaneous | 1199 // Miscellaneous |
| 1212 void clc(); | 1200 void clc(); |
| 1213 void cld(); | 1201 void cld(); |
| 1214 void cpuid(); | 1202 void cpuid(); |
| 1215 void hlt(); | 1203 void hlt(); |
| 1216 void int3(); | 1204 void int3(); |
| 1217 void nop(); | 1205 void nop(); |
| 1218 void ret(int imm16); | 1206 void ret(int imm16); |
| 1219 void setcc(Condition cc, Register reg); | 1207 void setcc(Condition cc, Register reg); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1245 | 1233 |
| 1246 // Calls directly to the given address using a relative offset. | 1234 // Calls directly to the given address using a relative offset. |
| 1247 // Should only ever be used in Code objects for calls within the | 1235 // Should only ever be used in Code objects for calls within the |
| 1248 // same Code object. Should not be used when generating new code (use labels), | 1236 // same Code object. Should not be used when generating new code (use labels), |
| 1249 // but only when patching existing code. | 1237 // but only when patching existing code. |
| 1250 void call(Address target); | 1238 void call(Address target); |
| 1251 | 1239 |
| 1252 // Call near absolute indirect, address in register | 1240 // Call near absolute indirect, address in register |
| 1253 void call(Register adr); | 1241 void call(Register adr); |
| 1254 | 1242 |
| 1255 // Call near indirect | |
| 1256 void call(const Operand& operand); | |
| 1257 | |
| 1258 // Jumps | 1243 // Jumps |
| 1259 // Jump short or near relative. | 1244 // Jump short or near relative. |
| 1260 // Use a 32-bit signed displacement. | 1245 // Use a 32-bit signed displacement. |
| 1261 // Unconditional jump to L | 1246 // Unconditional jump to L |
| 1262 void jmp(Label* L, Label::Distance distance = Label::kFar); | 1247 void jmp(Label* L, Label::Distance distance = Label::kFar); |
| 1263 void jmp(Address entry, RelocInfo::Mode rmode); | 1248 void jmp(Address entry, RelocInfo::Mode rmode); |
| 1264 void jmp(Handle<Code> target, RelocInfo::Mode rmode); | 1249 void jmp(Handle<Code> target, RelocInfo::Mode rmode); |
| 1265 | 1250 |
| 1266 // Jump near absolute indirect (r64) | 1251 // Jump near absolute indirect (r64) |
| 1267 void jmp(Register adr); | 1252 void jmp(Register adr); |
| 1268 | 1253 |
| 1269 // Jump near absolute indirect (m64) | |
| 1270 void jmp(const Operand& src); | |
| 1271 | |
| 1272 // Conditional jumps | 1254 // Conditional jumps |
| 1273 void j(Condition cc, | 1255 void j(Condition cc, |
| 1274 Label* L, | 1256 Label* L, |
| 1275 Label::Distance distance = Label::kFar); | 1257 Label::Distance distance = Label::kFar); |
| 1276 void j(Condition cc, Address entry, RelocInfo::Mode rmode); | 1258 void j(Condition cc, Address entry, RelocInfo::Mode rmode); |
| 1277 void j(Condition cc, Handle<Code> target, RelocInfo::Mode rmode); | 1259 void j(Condition cc, Handle<Code> target, RelocInfo::Mode rmode); |
| 1278 | 1260 |
| 1279 // Floating-point operations | 1261 // Floating-point operations |
| 1280 void fld(int i); | 1262 void fld(int i); |
| 1281 | 1263 |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1484 } | 1466 } |
| 1485 | 1467 |
| 1486 static bool IsNop(Address addr); | 1468 static bool IsNop(Address addr); |
| 1487 | 1469 |
| 1488 // Avoid overflows for displacements etc. | 1470 // Avoid overflows for displacements etc. |
| 1489 static const int kMaximalBufferSize = 512*MB; | 1471 static const int kMaximalBufferSize = 512*MB; |
| 1490 | 1472 |
| 1491 byte byte_at(int pos) { return buffer_[pos]; } | 1473 byte byte_at(int pos) { return buffer_[pos]; } |
| 1492 void set_byte_at(int pos, byte value) { buffer_[pos] = value; } | 1474 void set_byte_at(int pos, byte value) { buffer_[pos] = value; } |
| 1493 | 1475 |
| 1476 protected: |
| 1477 // Call near indirect |
| 1478 void call(const Operand& operand); |
| 1479 |
| 1480 // Jump near absolute indirect (m64) |
| 1481 void jmp(const Operand& src); |
| 1482 |
| 1494 private: | 1483 private: |
| 1495 byte* addr_at(int pos) { return buffer_ + pos; } | 1484 byte* addr_at(int pos) { return buffer_ + pos; } |
| 1496 uint32_t long_at(int pos) { | 1485 uint32_t long_at(int pos) { |
| 1497 return *reinterpret_cast<uint32_t*>(addr_at(pos)); | 1486 return *reinterpret_cast<uint32_t*>(addr_at(pos)); |
| 1498 } | 1487 } |
| 1499 void long_at_put(int pos, uint32_t x) { | 1488 void long_at_put(int pos, uint32_t x) { |
| 1500 *reinterpret_cast<uint32_t*>(addr_at(pos)) = x; | 1489 *reinterpret_cast<uint32_t*>(addr_at(pos)) = x; |
| 1501 } | 1490 } |
| 1502 | 1491 |
| 1503 // code emission | 1492 // code emission |
| (...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1744 private: | 1733 private: |
| 1745 Assembler* assembler_; | 1734 Assembler* assembler_; |
| 1746 #ifdef DEBUG | 1735 #ifdef DEBUG |
| 1747 int space_before_; | 1736 int space_before_; |
| 1748 #endif | 1737 #endif |
| 1749 }; | 1738 }; |
| 1750 | 1739 |
| 1751 } } // namespace v8::internal | 1740 } } // namespace v8::internal |
| 1752 | 1741 |
| 1753 #endif // V8_X64_ASSEMBLER_X64_H_ | 1742 #endif // V8_X64_ASSEMBLER_X64_H_ |
| OLD | NEW |