diff --git a/src/x64/assembler-x64.cc b/src/x64/assembler-x64.cc index 9ee6f666c8..69890eb4a4 100644 --- a/src/x64/assembler-x64.cc +++ b/src/x64/assembler-x64.cc @@ -33,6 +33,9 @@ namespace v8 { namespace internal { Register no_reg = { -1 }; +Register rax = { 0 }; +Register rcx = { 1 }; +Register rsi = { 7 }; // Safe default is no features. @@ -239,10 +242,39 @@ void Assembler::emit_operand(Register reg, const Operand& adr) { } -void Assembler::int3() { +void Assembler::add(Register dst, const Operand& src) { EnsureSpace ensure_space(this); last_pc_ = pc_; - EMIT(0xCC); + emit_rex_64(dst, src); + EMIT(0x03); + emit_operand(dst, src); +} + + +void Assembler::add(Register dst, Register src) { + EnsureSpace ensure_space(this); + last_pc_ = pc_; + emit_rex_64(dst, src); + EMIT(0x03); + EMIT(0xC0 | (src.code() & 0x7) << 3 | (dst.code() & 0x7)); +} + + +void Assembler::dec(Register dst) { + EnsureSpace ensure_space(this); + last_pc_ = pc_; + emit_rex_64(rcx, dst); + EMIT(0xFF); + EMIT(0xC8 | (dst.code() & 0x7)); +} + + +void Assembler::dec(const Operand& dst) { + EnsureSpace ensure_space(this); + last_pc_ = pc_; + emit_rex_64(rax, dst); + EMIT(0xFF); + emit_operand(rcx, dst); } @@ -253,24 +285,28 @@ void Assembler::hlt() { } -void Assembler::nop() { +void Assembler::inc(Register dst) { EnsureSpace ensure_space(this); last_pc_ = pc_; - EMIT(0x90); + emit_rex_64(rax, dst); + EMIT(0xFF); + EMIT(0xC0 | (dst.code() & 0x7)); } -void Assembler::ret(int imm16) { +void Assembler::inc(const Operand& dst) { EnsureSpace ensure_space(this); last_pc_ = pc_; - ASSERT(is_uint16(imm16)); - if (imm16 == 0) { - EMIT(0xC3); - } else { - EMIT(0xC2); - EMIT(imm16 & 0xFF); - EMIT((imm16 >> 8) & 0xFF); - } + emit_rex_64(rax, dst); + EMIT(0xFF); + emit_operand(rax, dst); +} + + +void Assembler::int3() { + EnsureSpace ensure_space(this); + last_pc_ = pc_; + EMIT(0xCC); } @@ -291,6 +327,64 @@ void Assembler::mov(Register dst, Register src) { EMIT(0xC0 | (src.code() & 0x7) << 3 | (dst.code() & 0x7)); } + +void Assembler::nop() { + EnsureSpace ensure_space(this); + last_pc_ = pc_; + EMIT(0x90); +} + +void Assembler::pop(Register dst) { + EnsureSpace ensure_space(this); + last_pc_ = pc_; + if (dst.code() & 0x8) { + emit_rex_64(rax, dst); + } + EMIT(0x58 | (dst.code() & 0x7)); +} + + +void Assembler::pop(const Operand& dst) { + EnsureSpace ensure_space(this); + last_pc_ = pc_; + emit_rex_64(rax, dst); // Could be omitted in some cases. + EMIT(0x8F); + emit_operand(rax, dst); +} + + +void Assembler::push(Register src) { + EnsureSpace ensure_space(this); + last_pc_ = pc_; + if (src.code() & 0x8) { + emit_rex_64(rax, src); + } + EMIT(0x50 | (src.code() & 0x7)); +} + + +void Assembler::push(const Operand& src) { + EnsureSpace ensure_space(this); + last_pc_ = pc_; + emit_rex_64(rsi, src); // Could be omitted in some cases. + EMIT(0xFF); + emit_operand(rsi, src); +} + + +void Assembler::ret(int imm16) { + EnsureSpace ensure_space(this); + last_pc_ = pc_; + ASSERT(is_uint16(imm16)); + if (imm16 == 0) { + EMIT(0xC3); + } else { + EMIT(0xC2); + EMIT(imm16 & 0xFF); + EMIT((imm16 >> 8) & 0xFF); + } +} + } } // namespace v8::internal diff --git a/src/x64/assembler-x64.h b/src/x64/assembler-x64.h index ffcaecdfb3..ba40eb3821 100644 --- a/src/x64/assembler-x64.h +++ b/src/x64/assembler-x64.h @@ -437,7 +437,8 @@ class Assembler : public Malloced { private: // The relocation writer's position is kGap bytes below the end of // the generated instructions. This leaves enough space for the - // longest possible ia32 instruction (17 bytes as of 9/26/06) and + // longest possible x64 instruction (There is a 15 byte limit on + // instruction length, ruling out some otherwise valid instructions) and // allows for a single, fast space check per instruction. static const int kGap = 32; @@ -475,22 +476,20 @@ class Assembler : public Malloced { // --------------------------------------------------------------------------- // Code generation // - // - function names correspond one-to-one to ia32 instruction mnemonics - // - unless specified otherwise, instructions operate on 32bit operands - // - instructions on 8bit (byte) operands/registers have a trailing '_b' - // - instructions on 16bit (word) operands/registers have a trailing '_w' - // - naming conflicts with C++ keywords are resolved via a trailing '_' - - // NOTE ON INTERFACE: Currently, the interface is not very consistent - // in the sense that some operations (e.g. mov()) can be called in more - // the one way to generate the same instruction: The Register argument - // can in some cases be replaced with an Operand(Register) argument. - // This should be cleaned up and made more orthogonal. The questions - // is: should we always use Operands instead of Registers where an - // Operand is possible, or should we have a Register (overloaded) form - // instead? We must be careful to make sure that the selected instruction - // is obvious from the parameters to avoid hard-to-find code generation - // bugs. + // Function names correspond one-to-one to x64 instruction mnemonics. + // Unless specified otherwise, instructions operate on 64-bit operands. + // + // If we need versions of an assembly instruction that operate on different + // width arguments, we add a single-letter suffix specifying the width. + // This is done for the following instructions: mov, cmp. + // There are no versions of these instructions without the suffix. + // - Instructions on 8-bit (byte) operands/registers have a trailing 'b'. + // - Instructions on 16-bit (word) operands/registers have a trailing 'w'. + // - Instructions on 32-bit (doubleword) operands/registers use 'l'. + // - Instructions on 64-bit (quadword) operands/registers use 'q'. + // + // Some mnemonics, such as "and", are the same as C++ keywords. + // Naming conflicts with C++ keywords are resolved by adding a trailing '_'. // Insert the smallest number of nop instructions // possible to align the pc offset to a multiple @@ -552,6 +551,7 @@ class Assembler : public Malloced { void adc(Register dst, int32_t imm32); void adc(Register dst, const Operand& src); + void add(Register dst, Register src); void add(Register dst, const Operand& src); void add(const Operand& dst, const Immediate& x);