X64: Added implementations of Set(..., Immediate) to macro assembler.

Removed duplicates comments in assembler-x64.cc.

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


git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2091 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
lrn@chromium.org 2009-06-03 10:30:50 +00:00
parent a41b41bf98
commit 5e83c2cc9c
6 changed files with 110 additions and 40 deletions

View File

@ -424,8 +424,6 @@ class ExternalReference BASE_EMBEDDED {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Utility functions // Utility functions
// Move these into inline file?
static inline bool is_intn(int x, int n) { static inline bool is_intn(int x, int n) {
return -(1 << (n-1)) <= x && x < (1 << (n-1)); return -(1 << (n-1)) <= x && x < (1 << (n-1));
} }

View File

@ -61,66 +61,66 @@ void Assembler::emitw(uint16_t x) {
} }
// High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
// REX.W is set. REX.X is cleared.
void Assembler::emit_rex_64(Register reg, Register rm_reg) { void Assembler::emit_rex_64(Register reg, Register rm_reg) {
emit(0x48 | (reg.code() & 0x8) >> 1 | rm_reg.code() >> 3); emit(0x48 | (reg.code() & 0x8) >> 1 | rm_reg.code() >> 3);
} }
// The high bit of reg is used for REX.R, the high bit of op's base
// register is used for REX.B, and the high bit of op's index register
// is used for REX.X. REX.W is set.
void Assembler::emit_rex_64(Register reg, const Operand& op) { void Assembler::emit_rex_64(Register reg, const Operand& op) {
emit(0x48 | (reg.code() & 0x8) >> 1 | op.rex_); emit(0x48 | (reg.code() & 0x8) >> 1 | op.rex_);
} }
// The high bit of the register is used for REX.B.
// REX.W is set and REX.R and REX.X are clear.
void Assembler::emit_rex_64(Register rm_reg) { void Assembler::emit_rex_64(Register rm_reg) {
ASSERT_EQ(rm_reg.code() & 0x0f, rm_reg.code()); ASSERT_EQ(rm_reg.code() & 0xf, rm_reg.code());
emit(0x48 | (rm_reg.code() >> 3)); emit(0x48 | (rm_reg.code() >> 3));
} }
// The high bit of op's base register is used for REX.B, and the high
// bit of op's index register is used for REX.X. REX.W is set and REX.R clear.
void Assembler::emit_rex_64(const Operand& op) { void Assembler::emit_rex_64(const Operand& op) {
emit(0x48 | op.rex_); emit(0x48 | op.rex_);
} }
// High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
// REX.W and REX.X are clear.
void Assembler::emit_rex_32(Register reg, Register rm_reg) { void Assembler::emit_rex_32(Register reg, Register rm_reg) {
emit(0x40 | (reg.code() & 0x8) >> 1 | rm_reg.code() >> 3); emit(0x40 | (reg.code() & 0x8) >> 1 | rm_reg.code() >> 3);
} }
// The high bit of reg is used for REX.R, the high bit of op's base
// register is used for REX.B, and the high bit of op's index register
// is used for REX.X. REX.W is cleared.
void Assembler::emit_rex_32(Register reg, const Operand& op) { void Assembler::emit_rex_32(Register reg, const Operand& op) {
emit(0x40 | (reg.code() & 0x8) >> 1 | op.rex_); emit(0x40 | (reg.code() & 0x8) >> 1 | op.rex_);
} }
// High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B. void Assembler::emit_rex_32(Register rm_reg) {
// REX.W and REX.X are cleared. If no REX bits are set, no byte is emitted. emit(0x40 | (rm_reg.code() & 0x8) >> 3);
void Assembler::emit_optional_rex_32(Register reg, Register rm_reg) { }
byte rex_bits = (reg.code() & 0x8) >> 1 | rm_reg.code() >> 3;
if (rex_bits) emit(0x40 | rex_bits);
void Assembler::emit_rex_32(const Operand& op) {
emit(0x40 | op.rex_);
}
void Assembler::emit_optional_rex_32(Register reg, Register rm_reg) {
byte rex_bits = (reg.code() & 0x8) >> 1 | rm_reg.code() >> 3;
if (rex_bits != 0) emit(0x40 | rex_bits);
} }
// The high bit of reg is used for REX.R, the high bit of op's base
// register is used for REX.B, and the high bit of op's index register
// is used for REX.X. REX.W is cleared. If no REX bits are set, nothing
// is emitted.
void Assembler::emit_optional_rex_32(Register reg, const Operand& op) { void Assembler::emit_optional_rex_32(Register reg, const Operand& op) {
byte rex_bits = (reg.code() & 0x8) >> 1 | op.rex_; byte rex_bits = (reg.code() & 0x8) >> 1 | op.rex_;
if (rex_bits) emit(0x40 | rex_bits); if (rex_bits != 0) emit(0x40 | rex_bits);
}
void Assembler::emit_optional_rex_32(Register rm_reg) {
if (rm_reg.code() & 0x8 != 0) emit(0x41);
}
void Assembler::emit_optional_rex_32(const Operand& op) {
if (op.rex_ != 0) emit(0x40 | op.rex_);
} }

View File

@ -685,6 +685,16 @@ void Assembler::movl(const Operand& dst, Register src) {
} }
void Assembler::movl(Register dst, Immediate value) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
emit_optional_rex_32(dst);
emit(0xC7);
emit(0xC0 | (dst.code() & 0x7));
emit(value); // Only 32-bit immediates are possible, not 8-bit immediates.
}
void Assembler::movq(Register dst, const Operand& src) { void Assembler::movq(Register dst, const Operand& src) {
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
last_pc_ = pc_; last_pc_ = pc_;
@ -703,15 +713,6 @@ void Assembler::movq(Register dst, Register src) {
} }
void Assembler::movq(const Operand& dst, Register src) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
emit_rex_64(src, dst);
emit(0x89);
emit_operand(src, dst);
}
void Assembler::movq(Register dst, Immediate value) { void Assembler::movq(Register dst, Immediate value) {
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
last_pc_ = pc_; last_pc_ = pc_;
@ -731,6 +732,15 @@ void Assembler::movq(Register dst, int64_t value, RelocInfo::Mode rmode) {
} }
void Assembler::movq(const Operand& dst, Register src) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
emit_rex_64(src, dst);
emit(0x89);
emit_operand(src, dst);
}
void Assembler::neg(Register dst) { void Assembler::neg(Register dst) {
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
last_pc_ = pc_; last_pc_ = pc_;

View File

@ -40,6 +40,19 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
// Utility functions
// Test whether a 64-bit value is in a specific range.
static inline bool is_uint32(int64_t x) {
const int64_t kUInt32Mask = V8_INT64_C(0xffffffff);
return x == x & kUInt32Mask;
}
static inline bool is_int32(int64_t x) {
const int64_t kMinIntValue = V8_INT64_C(-0x80000000);
return is_uint32(x - kMinIntValue);
}
// CPU Registers. // CPU Registers.
// //
// 1) We would prefer to use an enum, but enum values are assignment- // 1) We would prefer to use an enum, but enum values are assignment-
@ -410,12 +423,16 @@ class Assembler : public Malloced {
void movl(Register dst, Register src); void movl(Register dst, Register src);
void movl(Register dst, const Operand& src); void movl(Register dst, const Operand& src);
void movl(const Operand& dst, Register src); void movl(const Operand& dst, Register src);
// Load a 32-bit immediate value, zero-extended to 64 bits.
void movl(Register dst, Immediate imm32);
void movq(Register dst, int32_t imm32); void movq(Register dst, int32_t imm32);
void movq(Register dst, Immediate x);
void movq(Register dst, const Operand& src); void movq(Register dst, const Operand& src);
// Sign extends immediate 32-bit value to 64 bits.
void movq(Register dst, Immediate x);
void movq(Register dst, Register src); void movq(Register dst, Register src);
void movq(const Operand& dst, const Immediate& x);
// Move 64 bit register value to 64-bit memory location.
void movq(const Operand& dst, Register src); void movq(const Operand& dst, Register src);
// New x64 instructions to load a 64-bit immediate into a register. // New x64 instructions to load a 64-bit immediate into a register.
@ -426,6 +443,7 @@ class Assembler : public Malloced {
void movq(Register dst, const ExternalReference& ext, RelocInfo::Mode rmode); void movq(Register dst, const ExternalReference& ext, RelocInfo::Mode rmode);
void movq(Register dst, Handle<Object> handle, RelocInfo::Mode rmode); void movq(Register dst, Handle<Object> handle, RelocInfo::Mode rmode);
// New x64 instruction to load from an immediate 64-bit pointer into RAX. // New x64 instruction to load from an immediate 64-bit pointer into RAX.
void load_rax(void* ptr, RelocInfo::Mode rmode); void load_rax(void* ptr, RelocInfo::Mode rmode);
@ -874,6 +892,14 @@ class Assembler : public Malloced {
// is used for REX.X. REX.W is cleared. // is used for REX.X. REX.W is cleared.
inline void emit_rex_32(Register reg, const Operand& op); inline void emit_rex_32(Register reg, const Operand& op);
// High bit of rm_reg goes to REX.B.
// REX.W, REX.R and REX.X are clear.
inline void emit_rex_32(Register rm_reg);
// High bit of base goes to REX.B and high bit of index to REX.X.
// REX.W and REX.R are clear.
inline void emit_rex_32(const Operand &);
// High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B. // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
// REX.W is cleared. If no REX bits are set, no byte is emitted. // REX.W is cleared. If no REX bits are set, no byte is emitted.
inline void emit_optional_rex_32(Register reg, Register rm_reg); inline void emit_optional_rex_32(Register reg, Register rm_reg);
@ -884,6 +910,15 @@ class Assembler : public Malloced {
// is emitted. // is emitted.
inline void emit_optional_rex_32(Register reg, const Operand& op); inline void emit_optional_rex_32(Register reg, const Operand& op);
// Optionally do as emit_rex_32(Register) if the register number has
// the high bit set.
inline void emit_optional_rex_32(Register rm_reg);
// Optionally do as emit_rex_32(const Operand&) if the operand register
// numbers have a high bit set.
inline void emit_optional_rex_32(const Operand& op);
// Emit the Mod/RM byte, and optionally the SIB byte and // Emit the Mod/RM byte, and optionally the SIB byte and
// 1- or 4-byte offset for a memory operand. Also encodes // 1- or 4-byte offset for a memory operand. Also encodes
// the second operand of the operation, a register or operation // the second operand of the operation, a register or operation

View File

@ -29,6 +29,7 @@
#include "bootstrapper.h" #include "bootstrapper.h"
#include "codegen-inl.h" #include "codegen-inl.h"
#include "macro-assembler-x64.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
@ -45,4 +46,28 @@ void MacroAssembler::TailCallRuntime(ExternalReference const& a, int b) {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
void MacroAssembler::Set(Register dst, int64_t x) {
if (is_int32(x)) {
movq(dst, Immediate(x));
} else if (is_uint32(x)) {
movl(dst, Immediate(x));
} else {
movq(dst, x, RelocInfo::NONE);
}
}
void MacroAssembler::Set(const Operand& dst, int64_t x) {
if (is_int32(x)) {
movq(kScratchRegister, Immediate(x));
} else if (is_uint32(x)) {
movl(kScratchRegister, Immediate(x));
} else {
movq(kScratchRegister, x, RelocInfo::NONE);
}
movq(dst, kScratchRegister);
}
} } // namespace v8::internal } } // namespace v8::internal

View File

@ -33,6 +33,8 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
static const Register kScratchRegister = r10;
// Forward declaration. // Forward declaration.
class JumpTarget; class JumpTarget;
@ -137,8 +139,8 @@ class MacroAssembler: public Assembler {
void GetBuiltinEntry(Register target, Builtins::JavaScript id); void GetBuiltinEntry(Register target, Builtins::JavaScript id);
// Expression support // Expression support
void Set(Register dst, const Immediate& x); void Set(Register dst, int64_t x);
void Set(const Operand& dst, const Immediate& x); void Set(const Operand& dst, int64_t x);
// Compare object type for heap object. // Compare object type for heap object.
// Incoming register is heap_object and outgoing register is map. // Incoming register is heap_object and outgoing register is map.