| 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 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 56 // 3) By not using an enum, we are possibly preventing the compiler from | 56 // 3) By not using an enum, we are possibly preventing the compiler from |
| 57 // doing certain constant folds, which may significantly reduce the | 57 // doing certain constant folds, which may significantly reduce the |
| 58 // code generated for some assembly instructions (because they boil down | 58 // code generated for some assembly instructions (because they boil down |
| 59 // to a few constants). If this is a problem, we could change the code | 59 // to a few constants). If this is a problem, we could change the code |
| 60 // such that we use an enum in optimized mode, and the struct in debug | 60 // such that we use an enum in optimized mode, and the struct in debug |
| 61 // mode. This way we get the compile-time error checking in debug mode | 61 // mode. This way we get the compile-time error checking in debug mode |
| 62 // and best performance in optimized code. | 62 // and best performance in optimized code. |
| 63 // | 63 // |
| 64 | 64 |
| 65 struct Register { | 65 struct Register { |
| 66 static Register toRegister(int code) { |
| 67 Register r = {code}; |
| 68 return r; |
| 69 } |
| 66 bool is_valid() const { return 0 <= code_ && code_ < 16; } | 70 bool is_valid() const { return 0 <= code_ && code_ < 16; } |
| 67 bool is(Register reg) const { return code_ == reg.code_; } | 71 bool is(Register reg) const { return code_ == reg.code_; } |
| 68 // The byte-register distinction of ai32 has dissapeared. | 72 // The byte-register distinction of ai32 has dissapeared. |
| 69 bool is_byte_register() const { return false; } | 73 bool is_byte_register() const { return false; } |
| 70 int code() const { | 74 int code() const { |
| 71 ASSERT(is_valid()); | 75 ASSERT(is_valid()); |
| 72 return code_; | 76 return code_; |
| 73 } | 77 } |
| 74 int bit() const { | 78 int bit() const { |
| 75 UNIMPLEMENTED(); | 79 UNIMPLEMENTED(); |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 200 ? no_hint | 204 ? no_hint |
| 201 : ((hint == not_taken) ? taken : not_taken); | 205 : ((hint == not_taken) ? taken : not_taken); |
| 202 } | 206 } |
| 203 | 207 |
| 204 | 208 |
| 205 // ----------------------------------------------------------------------------- | 209 // ----------------------------------------------------------------------------- |
| 206 // Machine instruction Immediates | 210 // Machine instruction Immediates |
| 207 | 211 |
| 208 class Immediate BASE_EMBEDDED { | 212 class Immediate BASE_EMBEDDED { |
| 209 public: | 213 public: |
| 210 inline explicit Immediate(int64_t x); | 214 explicit Immediate(int32_t value) : value_(value) {} |
| 211 inline explicit Immediate(const char* s); | |
| 212 inline explicit Immediate(const ExternalReference& ext); | |
| 213 inline explicit Immediate(Handle<Object> handle); | |
| 214 inline explicit Immediate(Smi* value); | 215 inline explicit Immediate(Smi* value); |
| 215 | 216 |
| 216 static Immediate CodeRelativeOffset(Label* label) { | |
| 217 return Immediate(label); | |
| 218 } | |
| 219 | |
| 220 bool is_zero() const { return x_ == 0 && rmode_ == RelocInfo::NONE; } | |
| 221 bool is_int8() const { | |
| 222 return -128 <= x_ && x_ < 128 && rmode_ == RelocInfo::NONE; | |
| 223 } | |
| 224 bool is_int16() const { | |
| 225 return -32768 <= x_ && x_ < 32768 && rmode_ == RelocInfo::NONE; | |
| 226 } | |
| 227 bool is_int32() const { | |
| 228 return V8_INT64_C(-2147483648) <= x_ | |
| 229 && x_ < V8_INT64_C(2147483648) | |
| 230 && rmode_ == RelocInfo::NONE; | |
| 231 } | |
| 232 | |
| 233 private: | 217 private: |
| 234 inline explicit Immediate(Label* value) { UNIMPLEMENTED(); } | 218 int32_t value_; |
| 235 | |
| 236 int64_t x_; | |
| 237 RelocInfo::Mode rmode_; | |
| 238 | 219 |
| 239 friend class Assembler; | 220 friend class Assembler; |
| 240 }; | 221 }; |
| 241 | 222 |
| 242 | 223 |
| 243 // ----------------------------------------------------------------------------- | 224 // ----------------------------------------------------------------------------- |
| 244 // Machine instruction Operands | 225 // Machine instruction Operands |
| 245 | 226 |
| 246 enum ScaleFactor { | 227 enum ScaleFactor { |
| 247 times_1 = 0, | 228 times_1 = 0, |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 415 void push(const Operand& src); | 396 void push(const Operand& src); |
| 416 void push(Label* label, RelocInfo::Mode relocation_mode); | 397 void push(Label* label, RelocInfo::Mode relocation_mode); |
| 417 | 398 |
| 418 void pop(Register dst); | 399 void pop(Register dst); |
| 419 void pop(const Operand& dst); | 400 void pop(const Operand& dst); |
| 420 | 401 |
| 421 void enter(const Immediate& size); | 402 void enter(const Immediate& size); |
| 422 void leave(); | 403 void leave(); |
| 423 | 404 |
| 424 // Moves | 405 // Moves |
| 425 void mov_b(Register dst, const Operand& src); | 406 void movb(Register dst, const Operand& src); |
| 426 void mov_b(const Operand& dst, int8_t imm8); | 407 void movb(const Operand& dst, int8_t imm8); |
| 427 void mov_b(const Operand& dst, Register src); | 408 void movb(const Operand& dst, Register src); |
| 428 | 409 |
| 429 void mov_w(Register dst, const Operand& src); | 410 void movq(Register dst, int32_t imm32); |
| 430 void mov_w(const Operand& dst, Register src); | 411 void movq(Register dst, Immediate x); |
| 412 void movq(Register dst, const Operand& src); |
| 413 void movq(Register dst, Register src); |
| 414 void movq(const Operand& dst, const Immediate& x); |
| 415 void movq(const Operand& dst, Register src); |
| 431 | 416 |
| 432 void mov(Register dst, int32_t imm32); | 417 // New x64 instructions to load a 64-bit immediate into a register. |
| 433 void mov(Register dst, const Immediate& x); | 418 // All 64-bit immediates must have a relocation mode. |
| 434 void mov(Register dst, Handle<Object> handle); | 419 void movq(Register dst, void* ptr, RelocInfo::Mode rmode); |
| 435 void mov(Register dst, const Operand& src); | 420 void movq(Register dst, int64_t value, RelocInfo::Mode rmode); |
| 436 void mov(Register dst, Register src); | 421 void movq(Register dst, const char* s, RelocInfo::Mode rmode); |
| 437 void mov(const Operand& dst, const Immediate& x); | 422 void movq(Register dst, const ExternalReference& ext, RelocInfo::Mode rmode); |
| 438 void mov(const Operand& dst, Handle<Object> handle); | 423 void movq(Register dst, Handle<Object> handle, RelocInfo::Mode rmode); |
| 439 void mov(const Operand& dst, Register src); | 424 |
| 425 // New x64 instruction to load from an immediate 64-bit pointer into RAX. |
| 426 void load_rax(void* ptr, RelocInfo::Mode rmode); |
| 440 | 427 |
| 441 void movsx_b(Register dst, const Operand& src); | 428 void movsx_b(Register dst, const Operand& src); |
| 442 | 429 |
| 443 void movsx_w(Register dst, const Operand& src); | 430 void movsx_w(Register dst, const Operand& src); |
| 444 | 431 |
| 445 void movzx_b(Register dst, const Operand& src); | 432 void movzx_b(Register dst, const Operand& src); |
| 446 | 433 |
| 447 void movzx_w(Register dst, const Operand& src); | 434 void movzx_w(Register dst, const Operand& src); |
| 448 | 435 |
| 449 // Conditional moves | 436 // Conditional moves |
| 450 void cmov(Condition cc, Register dst, int32_t imm32); | 437 void cmov(Condition cc, Register dst, int32_t imm32); |
| 451 void cmov(Condition cc, Register dst, Handle<Object> handle); | 438 void cmov(Condition cc, Register dst, Handle<Object> handle); |
| 452 void cmov(Condition cc, Register dst, const Operand& src); | 439 void cmov(Condition cc, Register dst, const Operand& src); |
| 453 | 440 |
| 454 // Exchange two registers | 441 // Exchange two registers |
| 455 void xchg(Register dst, Register src); | 442 void xchg(Register dst, Register src); |
| 456 | 443 |
| 457 // Arithmetics | 444 // Arithmetics |
| 458 void adc(Register dst, int32_t imm32); | 445 void add(Register dst, Register src) { |
| 459 void adc(Register dst, const Operand& src); | 446 arithmetic_op(0x03, dst, src); |
| 447 } |
| 460 | 448 |
| 461 void add(Register dst, Register src); | 449 void add(Register dst, const Operand& src) { |
| 462 void add(Register dst, const Operand& src); | 450 arithmetic_op(0x03, dst, src); |
| 463 void add(const Operand& dst, const Immediate& x); | 451 } |
| 452 |
| 453 void add(const Operand& dst, Register src) { |
| 454 arithmetic_op(0x01, src, dst); |
| 455 } |
| 456 |
| 457 void add(Register dst, Immediate src) { |
| 458 immediate_arithmetic_op(0x0, dst, src); |
| 459 } |
| 460 |
| 461 void add(const Operand& dst, Immediate src) { |
| 462 immediate_arithmetic_op(0x0, dst, src); |
| 463 } |
| 464 |
| 465 void cmp(Register dst, Register src) { |
| 466 arithmetic_op(0x3B, dst, src); |
| 467 } |
| 468 |
| 469 void cmp(Register dst, const Operand& src) { |
| 470 arithmetic_op(0x3B, dst, src); |
| 471 } |
| 472 |
| 473 void cmp(const Operand& dst, Register src) { |
| 474 arithmetic_op(0x39, src, dst); |
| 475 } |
| 476 |
| 477 void cmp(Register dst, Immediate src) { |
| 478 immediate_arithmetic_op(0x7, dst, src); |
| 479 } |
| 480 |
| 481 void cmp(const Operand& dst, Immediate src) { |
| 482 immediate_arithmetic_op(0x7, dst, src); |
| 483 } |
| 484 |
| 464 | 485 |
| 465 void and_(Register dst, int32_t imm32); | 486 void and_(Register dst, int32_t imm32); |
| 466 void and_(Register dst, const Operand& src); | 487 void and_(Register dst, const Operand& src); |
| 467 void and_(const Operand& src, Register dst); | 488 void and_(const Operand& src, Register dst); |
| 468 void and_(const Operand& dst, const Immediate& x); | 489 void and_(const Operand& dst, const Immediate& x); |
| 469 | 490 |
| 470 void cmpb(const Operand& op, int8_t imm8); | 491 void cmpb(const Operand& op, int8_t imm8); |
| 471 void cmpb_al(const Operand& op); | 492 void cmpb_al(const Operand& op); |
| 472 void cmpw_ax(const Operand& op); | 493 void cmpw_ax(const Operand& op); |
| 473 void cmpw(const Operand& op, Immediate imm16); | 494 void cmpw(const Operand& op, Immediate imm16); |
| 474 void cmp(Register reg, int32_t imm32); | |
| 475 void cmp(Register reg, Handle<Object> handle); | |
| 476 void cmp(Register reg, const Operand& op); | |
| 477 void cmp(const Operand& op, const Immediate& imm); | |
| 478 | 495 |
| 479 void dec_b(Register dst); | 496 void dec_b(Register dst); |
| 480 | 497 |
| 481 void dec(Register dst); | 498 void dec(Register dst); |
| 482 void dec(const Operand& dst); | 499 void dec(const Operand& dst); |
| 483 | 500 |
| 484 void cdq(); | 501 void cdq(); |
| 485 | 502 |
| 486 void idiv(Register src); | 503 void idiv(Register src); |
| 487 | 504 |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 709 byte byte_at(int pos) { return buffer_[pos]; } | 726 byte byte_at(int pos) { return buffer_[pos]; } |
| 710 uint32_t long_at(int pos) { | 727 uint32_t long_at(int pos) { |
| 711 return *reinterpret_cast<uint32_t*>(addr_at(pos)); | 728 return *reinterpret_cast<uint32_t*>(addr_at(pos)); |
| 712 } | 729 } |
| 713 void long_at_put(int pos, uint32_t x) { | 730 void long_at_put(int pos, uint32_t x) { |
| 714 *reinterpret_cast<uint32_t*>(addr_at(pos)) = x; | 731 *reinterpret_cast<uint32_t*>(addr_at(pos)) = x; |
| 715 } | 732 } |
| 716 | 733 |
| 717 // code emission | 734 // code emission |
| 718 void GrowBuffer(); | 735 void GrowBuffer(); |
| 719 inline void emit(uint32_t x); | 736 inline void emitl(uint32_t x); |
| 720 inline void emit(Handle<Object> handle); | 737 inline void emit(Handle<Object> handle); |
| 721 inline void emit(uint32_t x, RelocInfo::Mode rmode); | 738 inline void emitq(uint64_t x, RelocInfo::Mode rmode); |
| 722 inline void emit(const Immediate& x); | 739 void emit(Immediate x) { emitl(x.value_); } |
| 723 inline void emit_w(const Immediate& x); | |
| 724 | 740 |
| 725 // Emits a REX prefix that encodes a 64-bit operand size and | 741 // Emits a REX prefix that encodes a 64-bit operand size and |
| 726 // the top bit of both register codes. | 742 // the top bit of both register codes. |
| 743 // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B. |
| 744 // REX.W is set. |
| 727 inline void emit_rex_64(Register reg, Register rm_reg); | 745 inline void emit_rex_64(Register reg, Register rm_reg); |
| 728 | 746 |
| 729 // Emits a REX prefix that encodes a 64-bit operand size and | 747 // Emits a REX prefix that encodes a 64-bit operand size and |
| 730 // the top bit of the destination, index, and base register codes. | 748 // the top bit of the destination, index, and base register codes. |
| 749 // The high bit of reg is used for REX.R, the high bit of op's base |
| 750 // register is used for REX.B, and the high bit of op's index register |
| 751 // is used for REX.X. REX.W is set. |
| 731 inline void emit_rex_64(Register reg, const Operand& op); | 752 inline void emit_rex_64(Register reg, const Operand& op); |
| 732 | 753 |
| 733 // Emit the code-object-relative offset of the label's position | 754 // Emit the code-object-relative offset of the label's position |
| 734 inline void emit_code_relative_offset(Label* label); | 755 inline void emit_code_relative_offset(Label* label); |
| 735 | 756 |
| 736 // instruction generation | 757 // instruction generation |
| 737 void emit_arith_b(int op1, int op2, Register dst, int imm8); | 758 void emit_arith_b(int op1, int op2, Register dst, int imm8); |
| 738 | 759 |
| 739 // Emit a basic arithmetic instruction (i.e. first byte of the family is 0x81) | 760 // Emit a basic arithmetic instruction (i.e. first byte of the family is 0x81) |
| 740 // with a given destination expression and an immediate operand. It attempts | 761 // with a given destination expression and an immediate operand. It attempts |
| 741 // to use the shortest encoding possible. | 762 // to use the shortest encoding possible. |
| 742 // sel specifies the /n in the modrm byte (see the Intel PRM). | 763 // sel specifies the /n in the modrm byte (see the Intel PRM). |
| 764 void arithmetic_op(byte opcode, Register dst, Register src); |
| 765 void arithmetic_op(byte opcode, Register reg, const Operand& op); |
| 766 void immediate_arithmetic_op(byte subcode, Register dst, Immediate src); |
| 767 void immediate_arithmetic_op(byte subcode, const Operand& dst, Immediate src); |
| 768 |
| 743 void emit_arith(int sel, Operand dst, const Immediate& x); | 769 void emit_arith(int sel, Operand dst, const Immediate& x); |
| 744 | 770 |
| 745 void emit_operand(Register reg, const Operand& adr); | 771 void emit_operand(Register reg, const Operand& adr); |
| 746 | 772 |
| 747 void emit_farith(int b1, int b2, int i); | 773 void emit_farith(int b1, int b2, int i); |
| 748 | 774 |
| 749 // labels | 775 // labels |
| 750 void print(Label* L); | 776 void print(Label* L); |
| 751 void bind_to(Label* L, int pos); | 777 void bind_to(Label* L, int pos); |
| 752 void link_to(Label* L, Label* appendix); | 778 void link_to(Label* L, Label* appendix); |
| 753 | 779 |
| 754 // record reloc info for current pc_ | 780 // record reloc info for current pc_ |
| 755 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0); | 781 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0) { |
| 782 UNIMPLEMENTED(); |
| 783 } |
| 756 | 784 |
| 757 friend class CodePatcher; | 785 friend class CodePatcher; |
| 758 friend class EnsureSpace; | 786 friend class EnsureSpace; |
| 759 | 787 |
| 760 // Code buffer: | 788 // Code buffer: |
| 761 // The buffer into which code and relocation info are generated. | 789 // The buffer into which code and relocation info are generated. |
| 762 byte* buffer_; | 790 byte* buffer_; |
| 763 int buffer_size_; | 791 int buffer_size_; |
| 764 // True if the assembler owns the buffer, false if buffer is external. | 792 // True if the assembler owns the buffer, false if buffer is external. |
| 765 bool own_buffer_; | 793 bool own_buffer_; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 804 private: | 832 private: |
| 805 Assembler* assembler_; | 833 Assembler* assembler_; |
| 806 #ifdef DEBUG | 834 #ifdef DEBUG |
| 807 int space_before_; | 835 int space_before_; |
| 808 #endif | 836 #endif |
| 809 }; | 837 }; |
| 810 | 838 |
| 811 } } // namespace v8::internal | 839 } } // namespace v8::internal |
| 812 | 840 |
| 813 #endif // V8_X64_ASSEMBLER_X64_H_ | 841 #endif // V8_X64_ASSEMBLER_X64_H_ |
| OLD | NEW |