| 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 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 287 public: | 287 public: |
| 288 // Feature flags bit positions. They are mostly based on the CPUID spec. | 288 // Feature flags bit positions. They are mostly based on the CPUID spec. |
| 289 // (We assign CPUID itself to one of the currently reserved bits -- | 289 // (We assign CPUID itself to one of the currently reserved bits -- |
| 290 // feel free to change this if needed.) | 290 // feel free to change this if needed.) |
| 291 enum Feature { SSE3 = 32, SSE2 = 26, CMOV = 15, RDTSC = 4, CPUID = 10 }; | 291 enum Feature { SSE3 = 32, SSE2 = 26, CMOV = 15, RDTSC = 4, CPUID = 10 }; |
| 292 // Detect features of the target CPU. Set safe defaults if the serializer | 292 // Detect features of the target CPU. Set safe defaults if the serializer |
| 293 // is enabled (snapshots must be portable). | 293 // is enabled (snapshots must be portable). |
| 294 static void Probe(); | 294 static void Probe(); |
| 295 // Check whether a feature is supported by the target CPU. | 295 // Check whether a feature is supported by the target CPU. |
| 296 static bool IsSupported(Feature f) { | 296 static bool IsSupported(Feature f) { |
| 297 return (supported_ & (static_cast<uint64_t>(1) << f)) != 0; | 297 return (supported_ & (V8_UINT64_C(1) << f)) != 0; |
| 298 } | 298 } |
| 299 // Check whether a feature is currently enabled. | 299 // Check whether a feature is currently enabled. |
| 300 static bool IsEnabled(Feature f) { | 300 static bool IsEnabled(Feature f) { |
| 301 return (enabled_ & (static_cast<uint64_t>(1) << f)) != 0; | 301 return (enabled_ & (V8_UINT64_C(1) << f)) != 0; |
| 302 } | 302 } |
| 303 // Enable a specified feature within a scope. | 303 // Enable a specified feature within a scope. |
| 304 class Scope BASE_EMBEDDED { | 304 class Scope BASE_EMBEDDED { |
| 305 #ifdef DEBUG | 305 #ifdef DEBUG |
| 306 public: | 306 public: |
| 307 explicit Scope(Feature f) { | 307 explicit Scope(Feature f) { |
| 308 ASSERT(CpuFeatures::IsSupported(f)); | 308 ASSERT(CpuFeatures::IsSupported(f)); |
| 309 old_enabled_ = CpuFeatures::enabled_; | 309 old_enabled_ = CpuFeatures::enabled_; |
| 310 CpuFeatures::enabled_ |= (static_cast<uint64_t>(1) << f); | 310 CpuFeatures::enabled_ |= (V8_UINT64_C(1) << f); |
| 311 } | 311 } |
| 312 ~Scope() { CpuFeatures::enabled_ = old_enabled_; } | 312 ~Scope() { CpuFeatures::enabled_ = old_enabled_; } |
| 313 private: | 313 private: |
| 314 uint64_t old_enabled_; | 314 uint64_t old_enabled_; |
| 315 #else | 315 #else |
| 316 public: | 316 public: |
| 317 explicit Scope(Feature f) {} | 317 explicit Scope(Feature f) {} |
| 318 #endif | 318 #endif |
| 319 }; | 319 }; |
| 320 private: | 320 private: |
| (...skipping 27 matching lines...) Expand all Loading... |
| 348 // upon destruction of the assembler. | 348 // upon destruction of the assembler. |
| 349 Assembler(void* buffer, int buffer_size); | 349 Assembler(void* buffer, int buffer_size); |
| 350 ~Assembler(); | 350 ~Assembler(); |
| 351 | 351 |
| 352 // GetCode emits any pending (non-emitted) code and fills the descriptor | 352 // GetCode emits any pending (non-emitted) code and fills the descriptor |
| 353 // desc. GetCode() is idempotent; it returns the same result if no other | 353 // desc. GetCode() is idempotent; it returns the same result if no other |
| 354 // Assembler functions are invoked in between GetCode() calls. | 354 // Assembler functions are invoked in between GetCode() calls. |
| 355 void GetCode(CodeDesc* desc); | 355 void GetCode(CodeDesc* desc); |
| 356 | 356 |
| 357 // Read/Modify the code target in the branch/call instruction at pc. | 357 // Read/Modify the code target in the branch/call instruction at pc. |
| 358 inline static Address target_address_at(Address pc); | 358 // On the x64 architecture, the address is absolute, not relative. |
| 359 inline static void set_target_address_at(Address pc, Address target); | 359 static inline Address target_address_at(Address pc); |
| 360 static inline void set_target_address_at(Address pc, Address target); |
| 360 | 361 |
| 361 // Distance between the address of the code target in the call instruction | 362 // Distance between the address of the code target in the call instruction |
| 362 // and the return address | 363 // and the return address |
| 363 static const int kTargetAddrToReturnAddrDist = kPointerSize; | 364 static const int kTargetAddrToReturnAddrDist = kPointerSize; |
| 364 | 365 |
| 365 | 366 |
| 366 // --------------------------------------------------------------------------- | 367 // --------------------------------------------------------------------------- |
| 367 // Code generation | 368 // Code generation |
| 368 // | 369 // |
| 369 // Function names correspond one-to-one to x64 instruction mnemonics. | 370 // Function names correspond one-to-one to x64 instruction mnemonics. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 380 // | 381 // |
| 381 // Some mnemonics, such as "and", are the same as C++ keywords. | 382 // Some mnemonics, such as "and", are the same as C++ keywords. |
| 382 // Naming conflicts with C++ keywords are resolved by adding a trailing '_'. | 383 // Naming conflicts with C++ keywords are resolved by adding a trailing '_'. |
| 383 | 384 |
| 384 // Insert the smallest number of nop instructions | 385 // Insert the smallest number of nop instructions |
| 385 // possible to align the pc offset to a multiple | 386 // possible to align the pc offset to a multiple |
| 386 // of m. m must be a power of 2. | 387 // of m. m must be a power of 2. |
| 387 void Align(int m); | 388 void Align(int m); |
| 388 | 389 |
| 389 // Stack | 390 // Stack |
| 390 void pushad(); | 391 void pushfq(); |
| 391 void popad(); | 392 void popfq(); |
| 392 | 393 |
| 393 void pushfd(); | 394 void push(Immediate value); |
| 394 void popfd(); | |
| 395 | |
| 396 void push(const Immediate& x); | |
| 397 void push(Register src); | 395 void push(Register src); |
| 398 void push(const Operand& src); | 396 void push(const Operand& src); |
| 399 void push(Label* label, RelocInfo::Mode relocation_mode); | 397 void push(Label* label, RelocInfo::Mode relocation_mode); |
| 400 | 398 |
| 401 void pop(Register dst); | 399 void pop(Register dst); |
| 402 void pop(const Operand& dst); | 400 void pop(const Operand& dst); |
| 403 | 401 |
| 404 void enter(const Immediate& size); | 402 void enter(Immediate size); |
| 405 void leave(); | 403 void leave(); |
| 406 | 404 |
| 407 // Moves | 405 // Moves |
| 408 void movb(Register dst, const Operand& src); | 406 void movb(Register dst, const Operand& src); |
| 409 void movb(const Operand& dst, int8_t imm8); | 407 void movb(const Operand& dst, int8_t imm8); |
| 410 void movb(const Operand& dst, Register src); | 408 void movb(const Operand& dst, Register src); |
| 411 | 409 |
| 410 void movl(Register dst, Register src); |
| 411 void movl(Register dst, const Operand& src); |
| 412 void movl(const Operand& dst, Register src); |
| 413 |
| 412 void movq(Register dst, int32_t imm32); | 414 void movq(Register dst, int32_t imm32); |
| 413 void movq(Register dst, Immediate x); | 415 void movq(Register dst, Immediate x); |
| 414 void movq(Register dst, const Operand& src); | 416 void movq(Register dst, const Operand& src); |
| 415 void movq(Register dst, Register src); | 417 void movq(Register dst, Register src); |
| 416 void movq(const Operand& dst, const Immediate& x); | 418 void movq(const Operand& dst, const Immediate& x); |
| 417 void movq(const Operand& dst, Register src); | 419 void movq(const Operand& dst, Register src); |
| 418 | 420 |
| 419 // New x64 instructions to load a 64-bit immediate into a register. | 421 // New x64 instructions to load a 64-bit immediate into a register. |
| 420 // All 64-bit immediates must have a relocation mode. | 422 // All 64-bit immediates must have a relocation mode. |
| 421 void movq(Register dst, void* ptr, RelocInfo::Mode rmode); | 423 void movq(Register dst, void* ptr, RelocInfo::Mode rmode); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 508 void cmpb(const Operand& op, int8_t imm8); | 510 void cmpb(const Operand& op, int8_t imm8); |
| 509 void cmpb_al(const Operand& op); | 511 void cmpb_al(const Operand& op); |
| 510 void cmpw_ax(const Operand& op); | 512 void cmpw_ax(const Operand& op); |
| 511 void cmpw(const Operand& op, Immediate imm16); | 513 void cmpw(const Operand& op, Immediate imm16); |
| 512 | 514 |
| 513 void dec_b(Register dst); | 515 void dec_b(Register dst); |
| 514 | 516 |
| 515 void dec(Register dst); | 517 void dec(Register dst); |
| 516 void dec(const Operand& dst); | 518 void dec(const Operand& dst); |
| 517 | 519 |
| 518 void cdq(); | 520 // Sign-extends rax into rdx:rax. |
| 521 void cqo(); |
| 519 | 522 |
| 520 void idiv(Register src); | 523 void idiv(Register src); |
| 521 | 524 |
| 522 void imul(Register dst, const Operand& src); | 525 void imul(Register dst, const Operand& src); |
| 523 void imul(Register dst, Register src, int32_t imm32); | 526 void imul(Register dst, Register src, int32_t imm32); |
| 524 | 527 |
| 525 void inc(Register dst); | 528 void inc(Register dst); |
| 526 void inc(const Operand& dst); | 529 void inc(const Operand& dst); |
| 527 | 530 |
| 528 void lea(Register dst, const Operand& src); | 531 void lea(Register dst, const Operand& src); |
| (...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 823 *reinterpret_cast<uint32_t*>(addr_at(pos)) = x; | 826 *reinterpret_cast<uint32_t*>(addr_at(pos)) = x; |
| 824 } | 827 } |
| 825 | 828 |
| 826 // code emission | 829 // code emission |
| 827 void GrowBuffer(); | 830 void GrowBuffer(); |
| 828 | 831 |
| 829 void emit(byte x) { *pc_++ = x; } | 832 void emit(byte x) { *pc_++ = x; } |
| 830 inline void emitl(uint32_t x); | 833 inline void emitl(uint32_t x); |
| 831 inline void emit(Handle<Object> handle); | 834 inline void emit(Handle<Object> handle); |
| 832 inline void emitq(uint64_t x, RelocInfo::Mode rmode); | 835 inline void emitq(uint64_t x, RelocInfo::Mode rmode); |
| 836 inline void emitw(uint16_t x); |
| 833 void emit(Immediate x) { emitl(x.value_); } | 837 void emit(Immediate x) { emitl(x.value_); } |
| 834 | 838 |
| 835 // Emits a REX prefix that encodes a 64-bit operand size and | 839 // Emits a REX prefix that encodes a 64-bit operand size and |
| 836 // the top bit of both register codes. | 840 // the top bit of both register codes. |
| 837 // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B. | 841 // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B. |
| 838 // REX.W is set. | 842 // REX.W is set. |
| 839 inline void emit_rex_64(Register reg, Register rm_reg); | 843 inline void emit_rex_64(Register reg, Register rm_reg); |
| 840 | 844 |
| 841 // Emits a REX prefix that encodes a 64-bit operand size and | 845 // Emits a REX prefix that encodes a 64-bit operand size and |
| 842 // the top bit of the destination, index, and base register codes. | 846 // the top bit of the destination, index, and base register codes. |
| 843 // The high bit of reg is used for REX.R, the high bit of op's base | 847 // The high bit of reg is used for REX.R, the high bit of op's base |
| 844 // register is used for REX.B, and the high bit of op's index register | 848 // register is used for REX.B, and the high bit of op's index register |
| 845 // is used for REX.X. REX.W is set. | 849 // is used for REX.X. REX.W is set. |
| 846 inline void emit_rex_64(Register reg, const Operand& op); | 850 inline void emit_rex_64(Register reg, const Operand& op); |
| 847 | 851 |
| 848 // Emits a REX prefix that encodes a 64-bit operand size and | 852 // Emits a REX prefix that encodes a 64-bit operand size and |
| 849 // the top bit of the register code. | 853 // the top bit of the register code. |
| 850 // The high bit of register is used for REX.B. | 854 // The high bit of register is used for REX.B. |
| 851 // REX.W is set and REX.R and REX.X are clear. | 855 // REX.W is set and REX.R and REX.X are clear. |
| 852 inline void emit_rex_64(Register rm_reg); | 856 inline void emit_rex_64(Register rm_reg); |
| 853 | 857 |
| 854 // Emits a REX prefix that encodes a 64-bit operand size and | 858 // Emits a REX prefix that encodes a 64-bit operand size and |
| 855 // the top bit of the index and base register codes. | 859 // the top bit of the index and base register codes. |
| 856 // The high bit of op's base register is used for REX.B, and the high | 860 // The high bit of op's base register is used for REX.B, and the high |
| 857 // bit of op's index register is used for REX.X. | 861 // bit of op's index register is used for REX.X. |
| 858 // REX.W is set and REX.R clear. | 862 // REX.W is set and REX.R clear. |
| 859 inline void emit_rex_64(const Operand& op); | 863 inline void emit_rex_64(const Operand& op); |
| 860 | 864 |
| 865 // Emit a REX prefix that only sets REX.W to choose a 64-bit operand size. |
| 866 void emit_rex_64() { emit(0x48); } |
| 867 |
| 861 // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B. | 868 // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B. |
| 862 // REX.W is clear. | 869 // REX.W is clear. |
| 863 inline void emit_rex_32(Register reg, Register rm_reg); | 870 inline void emit_rex_32(Register reg, Register rm_reg); |
| 864 | 871 |
| 865 // The high bit of reg is used for REX.R, the high bit of op's base | 872 // The high bit of reg is used for REX.R, the high bit of op's base |
| 866 // register is used for REX.B, and the high bit of op's index register | 873 // register is used for REX.B, and the high bit of op's index register |
| 867 // is used for REX.X. REX.W is cleared. | 874 // is used for REX.X. REX.W is cleared. |
| 868 inline void emit_rex_32(Register reg, const Operand& op); | 875 inline void emit_rex_32(Register reg, const Operand& op); |
| 869 | 876 |
| 870 // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B. | 877 // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B. |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 966 private: | 973 private: |
| 967 Assembler* assembler_; | 974 Assembler* assembler_; |
| 968 #ifdef DEBUG | 975 #ifdef DEBUG |
| 969 int space_before_; | 976 int space_before_; |
| 970 #endif | 977 #endif |
| 971 }; | 978 }; |
| 972 | 979 |
| 973 } } // namespace v8::internal | 980 } } // namespace v8::internal |
| 974 | 981 |
| 975 #endif // V8_X64_ASSEMBLER_X64_H_ | 982 #endif // V8_X64_ASSEMBLER_X64_H_ |
| OLD | NEW |