X64: Added implementations of Set(..., Immediate) to macro assembler.
authorlrn@chromium.org <lrn@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 3 Jun 2009 10:30:50 +0000 (10:30 +0000)
committerlrn@chromium.org <lrn@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 3 Jun 2009 10:30:50 +0000 (10:30 +0000)
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

src/assembler.h
src/x64/assembler-x64-inl.h
src/x64/assembler-x64.cc
src/x64/assembler-x64.h
src/x64/macro-assembler-x64.cc
src/x64/macro-assembler-x64.h

index 597cf9c..66f952a 100644 (file)
@@ -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));
 }
index 8d82a53..830523e 100644 (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) {
   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_);
 }
 
 
index ed9f2ad..65716d5 100644 (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) {
   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_;
index be88162..983de41 100644 (file)
 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
index 5e6dd3d..968b459 100644 (file)
@@ -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
index 67c7bdd..61834e0 100644 (file)
@@ -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.