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:
parent
a41b41bf98
commit
5e83c2cc9c
@ -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));
|
||||||
}
|
}
|
||||||
|
@ -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_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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_;
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
Loading…
Reference in New Issue
Block a user