Implementation of a few more assembly instructions on x64

Review URL: http://codereview.chromium.org/113767

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2043 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
whesse@chromium.org 2009-05-25 14:00:30 +00:00
parent cee54f88a1
commit 80fba5a127
2 changed files with 124 additions and 30 deletions

View File

@ -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

View File

@ -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);