Author: [email protected]
Date: Tue Jun  2 06:40:52 2009
New Revision: 2089

Modified:
    branches/bleeding_edge/src/memory.h
    branches/bleeding_edge/src/x64/assembler-x64-inl.h
    branches/bleeding_edge/src/x64/assembler-x64.cc
    branches/bleeding_edge/src/x64/assembler-x64.h

Log:
Add miscellaneous operations to x64 assembler.
Review URL: http://codereview.chromium.org/113997

Modified: branches/bleeding_edge/src/memory.h
==============================================================================
--- branches/bleeding_edge/src/memory.h (original)
+++ branches/bleeding_edge/src/memory.h Tue Jun  2 06:40:52 2009
@@ -36,6 +36,10 @@

  class Memory {
   public:
+  static uint16_t& uint16_at(Address addr)  {
+    return *reinterpret_cast<uint16_t*>(addr);
+  }
+
    static uint32_t& uint32_at(Address addr)  {
      return *reinterpret_cast<uint32_t*>(addr);
    }

Modified: branches/bleeding_edge/src/x64/assembler-x64-inl.h
==============================================================================
--- branches/bleeding_edge/src/x64/assembler-x64-inl.h  (original)
+++ branches/bleeding_edge/src/x64/assembler-x64-inl.h  Tue Jun  2 06:40:52  
2009
@@ -55,6 +55,12 @@
  }


+void Assembler::emitw(uint16_t x) {
+  Memory::uint16_at(pc_) = x;
+  pc_ += sizeof(uint16_t);
+}
+
+
  // 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) {
@@ -118,14 +124,14 @@
  }


-void Assembler::set_target_address_at(byte* location, byte* value) {
-  UNIMPLEMENTED();
+Address Assembler::target_address_at(Address pc) {
+  return Memory::Address_at(pc);
  }


-byte* Assembler::target_address_at(byte* location) {
-  UNIMPLEMENTED();
-  return NULL;
+void Assembler::set_target_address_at(Address pc, Address target) {
+  Memory::Address_at(pc) = target;
+  CPU::FlushICache(pc, sizeof(intptr_t));
  }


@@ -166,6 +172,8 @@
    ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY);
    Assembler::set_target_address_at(pc_, target);
  }
+
+
  Object* RelocInfo::target_object() {
    ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
    return *reinterpret_cast<Object**>(pc_);

Modified: branches/bleeding_edge/src/x64/assembler-x64.cc
==============================================================================
--- branches/bleeding_edge/src/x64/assembler-x64.cc     (original)
+++ branches/bleeding_edge/src/x64/assembler-x64.cc     Tue Jun  2 06:40:52 2009
@@ -77,7 +77,73 @@
  uint64_t CpuFeatures::enabled_ = 0;

  void CpuFeatures::Probe()  {
-  // TODO(X64): UNIMPLEMENTED
+  ASSERT(Heap::HasBeenSetup());
+  ASSERT(supported_ == 0);
+  if (Serializer::enabled()) return;  // No features if we might serialize.
+
+  Assembler assm(NULL, 0);
+  Label cpuid, done;
+#define __ assm.
+  // Save old esp, since we are going to modify the stack.
+  __ push(rbp);
+  __ pushfq();
+  __ push(rcx);
+  __ push(rbx);
+  __ movq(rbp, rsp);
+
+  // If we can modify bit 21 of the EFLAGS register, then CPUID is  
supported.
+  __ pushfq();
+  __ pop(rax);
+  __ movq(rdx, rax);
+  __ xor_(rax, Immediate(0x200000));  // Flip bit 21.
+  __ push(rax);
+  __ popfq();
+  __ pushfq();
+  __ pop(rax);
+  __ xor_(rax, rdx);  // Different if CPUID is supported.
+  __ j(not_zero, &cpuid);
+
+  // CPUID not supported. Clear the supported features in edx:eax.
+  __ xor_(rax, rax);
+  __ jmp(&done);
+
+  // Invoke CPUID with 1 in eax to get feature information in
+  // ecx:edx. Temporarily enable CPUID support because we know it's
+  // safe here.
+  __ bind(&cpuid);
+  __ movq(rax, Immediate(1));
+  supported_ = (1 << CPUID);
+  { Scope fscope(CPUID);
+    __ cpuid();
+  }
+  supported_ = 0;
+
+  // Move the result from ecx:edx to rax and make sure to mark the
+  // CPUID feature as supported.
+  __ movl(rax, rdx);  // Zero-extended to 64 bits.
+  __ shl(rcx, Immediate(32));
+  __ or_(rax, rcx);
+  __ or_(rax, Immediate(1 << CPUID));
+
+  // Done.
+  __ bind(&done);
+  __ movq(rsp, rbp);
+  __ pop(rbx);
+  __ pop(rcx);
+  __ popfq();
+  __ pop(rbp);
+  __ ret(0);
+#undef __
+
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  Object* code =
+      Heap::CreateCode(desc, NULL, Code::ComputeFlags(Code::STUB), NULL);
+  if (!code->IsCode()) return;
+  LOG(CodeCreateEvent("Builtin", Code::cast(code), "CpuFeatures::Probe"));
+  typedef uint64_t (*F0)();
+  F0 probe = FUNCTION_CAST<F0>(Code::cast(code)->entry());
+  supported_ = probe();
  }

  //  
-----------------------------------------------------------------------------
@@ -368,6 +434,26 @@
  }


+void Assembler::bt(const Operand& dst, Register src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit_rex_64(src, dst);
+  emit(0x0F);
+  emit(0xA3);
+  emit_operand(src, dst);
+}
+
+
+void Assembler::bts(const Operand& dst, Register src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit_rex_64(src, dst);
+  emit(0x0F);
+  emit(0xAB);
+  emit_operand(src, dst);
+}
+
+
  void Assembler::call(Label* L) {
    EnsureSpace ensure_space(this);
    last_pc_ = pc_;
@@ -401,6 +487,23 @@
  }


+void Assembler::cpuid() {
+  ASSERT(CpuFeatures::IsEnabled(CpuFeatures::CPUID));
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit(0x0F);
+  emit(0xA2);
+}
+
+
+void Assembler::cqo() {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit_rex_64();
+  emit(0x99);
+}
+
+
  void Assembler::dec(Register dst) {
    EnsureSpace ensure_space(this);
    last_pc_ = pc_;
@@ -419,6 +522,15 @@
  }


+void Assembler::enter(Immediate size) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit(0xC8);
+  emitw(size.value_);  // 16 bit operand, always.
+  emit(0);
+}
+
+
  void Assembler::hlt() {
    EnsureSpace ensure_space(this);
    last_pc_ = pc_;
@@ -530,6 +642,49 @@
  }


+void Assembler::lea(Register dst, const Operand& src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit_rex_64(dst, src);
+  emit(0x8D);
+  emit_operand(dst, src);
+}
+
+
+void Assembler::leave() {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit(0xC9);
+}
+
+
+void Assembler::movl(Register dst, const Operand& src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit_optional_rex_32(dst, src);
+  emit(0x8B);
+  emit_operand(dst, src);
+}
+
+
+void Assembler::movl(Register dst, Register src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit_optional_rex_32(dst, src);
+  emit(0x8B);
+  emit(0xC0 | (dst.code() & 0x7) << 3 | (src.code() & 0x7));
+}
+
+
+void Assembler::movl(const Operand& dst, Register src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit_optional_rex_32(src, dst);
+  emit(0x89);
+  emit_operand(src, dst);
+}
+
+
  void Assembler::movq(Register dst, const Operand& src) {
    EnsureSpace ensure_space(this);
    last_pc_ = pc_;
@@ -548,6 +703,15 @@
  }


+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_;
@@ -716,6 +880,13 @@
  }


+void Assembler::popfq() {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit(0x9D);
+}
+
+
  void Assembler::push(Register src) {
    EnsureSpace ensure_space(this);
    last_pc_ = pc_;
@@ -735,6 +906,43 @@
  }


+void Assembler::push(Immediate value) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  if (is_int8(value.value_)) {
+    emit(0x6A);
+    emit(value.value_);  // Emit low byte of value.
+  } else {
+    emit(0x68);
+    emitl(value.value_);
+  }
+}
+
+
+void Assembler::pushfq() {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit(0x9C);
+}
+
+
+void Assembler::rcl(Register dst, uint8_t imm8) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  ASSERT(is_uint6(imm8));  // illegal shift count
+  if (imm8 == 1) {
+    emit_rex_64(dst);
+    emit(0xD1);
+    emit(0xD0 | (dst.code() & 0x7));
+  } else {
+    emit_rex_64(dst);
+    emit(0xC1);
+    emit(0xD0 | (dst.code() & 0x7));
+    emit(imm8);
+  }
+}
+
+
  void Assembler::ret(int imm16) {
    EnsureSpace ensure_space(this);
    last_pc_ = pc_;
@@ -745,6 +953,21 @@
      emit(0xC2);
      emit(imm16 & 0xFF);
      emit((imm16 >> 8) & 0xFF);
+  }
+}
+
+
+void Assembler::xchg(Register dst, Register src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  if (src.is(rax) || dst.is(rax)) {  // Single-byte encoding
+    Register other = src.is(rax) ? dst : src;
+    emit_rex_64(other);
+    emit(0x90 | (other.code() & 0x7));
+  } else {
+    emit_rex_64(src, dst);
+    emit(0x87);
+    emit(0xC0 | (src.code() & 0x7) << 3 | (dst.code() & 0x7));
    }
  }


Modified: branches/bleeding_edge/src/x64/assembler-x64.h
==============================================================================
--- branches/bleeding_edge/src/x64/assembler-x64.h      (original)
+++ branches/bleeding_edge/src/x64/assembler-x64.h      Tue Jun  2 06:40:52 2009
@@ -294,11 +294,11 @@
    static void Probe();
    // Check whether a feature is supported by the target CPU.
    static bool IsSupported(Feature f) {
-    return (supported_ & (static_cast<uint64_t>(1) << f)) != 0;
+    return (supported_ & (V8_UINT64_C(1) << f)) != 0;
    }
    // Check whether a feature is currently enabled.
    static bool IsEnabled(Feature f) {
-    return (enabled_ & (static_cast<uint64_t>(1) << f)) != 0;
+    return (enabled_ & (V8_UINT64_C(1) << f)) != 0;
    }
    // Enable a specified feature within a scope.
    class Scope BASE_EMBEDDED {
@@ -307,7 +307,7 @@
      explicit Scope(Feature f) {
        ASSERT(CpuFeatures::IsSupported(f));
        old_enabled_ = CpuFeatures::enabled_;
-      CpuFeatures::enabled_ |= (static_cast<uint64_t>(1) << f);
+      CpuFeatures::enabled_ |= (V8_UINT64_C(1) << f);
      }
      ~Scope() { CpuFeatures::enabled_ = old_enabled_; }
     private:
@@ -355,8 +355,9 @@
    void GetCode(CodeDesc* desc);

    // Read/Modify the code target in the branch/call instruction at pc.
-  inline static Address target_address_at(Address pc);
-  inline static void set_target_address_at(Address pc, Address target);
+  // On the x64 architecture, the address is absolute, not relative.
+  static inline Address target_address_at(Address pc);
+  static inline void set_target_address_at(Address pc, Address target);

    // Distance between the address of the code target in the call  
instruction
    // and the return address
@@ -387,13 +388,10 @@
    void Align(int m);

    // Stack
-  void pushad();
-  void popad();
+  void pushfq();
+  void popfq();

-  void pushfd();
-  void popfd();
-
-  void push(const Immediate& x);
+  void push(Immediate value);
    void push(Register src);
    void push(const Operand& src);
    void push(Label* label, RelocInfo::Mode relocation_mode);
@@ -401,7 +399,7 @@
    void pop(Register dst);
    void pop(const Operand& dst);

-  void enter(const Immediate& size);
+  void enter(Immediate size);
    void leave();

    // Moves
@@ -409,6 +407,10 @@
    void movb(const Operand& dst, int8_t imm8);
    void movb(const Operand& dst, Register src);

+  void movl(Register dst, Register src);
+  void movl(Register dst, const Operand& src);
+  void movl(const Operand& dst, Register src);
+
    void movq(Register dst, int32_t imm32);
    void movq(Register dst, Immediate x);
    void movq(Register dst, const Operand& src);
@@ -515,7 +517,8 @@
    void dec(Register dst);
    void dec(const Operand& dst);

-  void cdq();
+  // Sign-extends rax into rdx:rax.
+  void cqo();

    void idiv(Register src);

@@ -830,6 +833,7 @@
    inline void emitl(uint32_t x);
    inline void emit(Handle<Object> handle);
    inline void emitq(uint64_t x, RelocInfo::Mode rmode);
+  inline void emitw(uint16_t x);
    void emit(Immediate x) { emitl(x.value_); }

    // Emits a REX prefix that encodes a 64-bit operand size and
@@ -857,6 +861,9 @@
    // bit of op's index register is used for REX.X.
    // REX.W is set and REX.R clear.
    inline void emit_rex_64(const Operand& op);
+
+  // Emit a REX prefix that only sets REX.W to choose a 64-bit operand  
size.
+  void emit_rex_64() { emit(0x48); }

    // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
    // REX.W is clear.

--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---

Reply via email to