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 |