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:
parent
cee54f88a1
commit
80fba5a127
@ -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
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user