// -----------------------------------------------------------------------------
// 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));
}
}
-// 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_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) emit(0x40 | rex_bits);
+ 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_);
}
}
+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_;
}
-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_;
}
+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_;
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-
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.
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);
// 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);
// 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
#include "bootstrapper.h"
#include "codegen-inl.h"
+#include "macro-assembler-x64.h"
namespace v8 {
namespace internal {
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 {
namespace internal {
+static const Register kScratchRegister = r10;
+
// Forward declaration.
class JumpTarget;
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.