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
|
||||
|
||||
// Move these into inline file?
|
||||
|
||||
static inline bool is_intn(int x, int n) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
ASSERT_EQ(rm_reg.code() & 0x0f, rm_reg.code());
|
||||
ASSERT_EQ(rm_reg.code() & 0xf, rm_reg.code());
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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.
|
||||
// REX.W and REX.X are cleared. If no REX bits are set, no byte is emitted.
|
||||
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(Register rm_reg) {
|
||||
emit(0x40 | (rm_reg.code() & 0x8) >> 3);
|
||||
}
|
||||
|
||||
|
||||
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) {
|
||||
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) {
|
||||
EnsureSpace ensure_space(this);
|
||||
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) {
|
||||
EnsureSpace ensure_space(this);
|
||||
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) {
|
||||
EnsureSpace ensure_space(this);
|
||||
last_pc_ = pc_;
|
||||
|
@ -40,6 +40,19 @@
|
||||
namespace v8 {
|
||||
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.
|
||||
//
|
||||
// 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, const Operand& 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, Immediate x);
|
||||
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(const Operand& dst, const Immediate& x);
|
||||
|
||||
// Move 64 bit register value to 64-bit memory location.
|
||||
void movq(const Operand& dst, Register src);
|
||||
|
||||
// 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, Handle<Object> handle, RelocInfo::Mode rmode);
|
||||
|
||||
|
||||
// New x64 instruction to load from an immediate 64-bit pointer into RAX.
|
||||
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.
|
||||
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.
|
||||
// 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);
|
||||
@ -884,6 +910,15 @@ class Assembler : public Malloced {
|
||||
// is emitted.
|
||||
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
|
||||
// 1- or 4-byte offset for a memory operand. Also encodes
|
||||
// the second operand of the operation, a register or operation
|
||||
|
@ -29,6 +29,7 @@
|
||||
|
||||
#include "bootstrapper.h"
|
||||
#include "codegen-inl.h"
|
||||
#include "macro-assembler-x64.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
@ -45,4 +46,28 @@ void MacroAssembler::TailCallRuntime(ExternalReference const& a, int b) {
|
||||
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
|
||||
|
@ -33,6 +33,8 @@
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
static const Register kScratchRegister = r10;
|
||||
|
||||
// Forward declaration.
|
||||
class JumpTarget;
|
||||
|
||||
@ -137,8 +139,8 @@ class MacroAssembler: public Assembler {
|
||||
void GetBuiltinEntry(Register target, Builtins::JavaScript id);
|
||||
|
||||
// Expression support
|
||||
void Set(Register dst, const Immediate& x);
|
||||
void Set(const Operand& dst, const Immediate& x);
|
||||
void Set(Register dst, int64_t x);
|
||||
void Set(const Operand& dst, int64_t x);
|
||||
|
||||
// Compare object type for heap object.
|
||||
// Incoming register is heap_object and outgoing register is map.
|
||||
|
Loading…
Reference in New Issue
Block a user