Author: [email protected]
Date: Wed May 27 01:15:31 2009
New Revision: 2062

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

Log:
Implement memory operands for instructions in the x64 assembler.
Review URL: http://codereview.chromium.org/113841

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  Wed May 27 01:15:31  
2009
@@ -173,13 +173,32 @@
    return reinterpret_cast<Object**>(pc_ + 1);
  }

+//  
-----------------------------------------------------------------------------
+// Implementation of Operand
+
+Operand::Operand(Register base, int32_t disp) {
+  len_ = 1;
+  if (base.is(rsp) || base.is(r12)) {
+    // SIB byte is needed to encode (rsp + offset) or (r12 + offset).
+    set_sib(times_1, rsp, base);
+  }
+
+  if (disp == 0 && !base.is(rbp) && !base.is(r13)) {
+    set_modrm(0, rsp);
+  } else if (is_int8(disp)) {
+    set_modrm(1, base);
+    set_disp8(disp);
+  } else {
+    set_modrm(2, base);
+    set_disp32(disp);
+  }
+}

  void Operand::set_modrm(int mod, Register rm) {
    ASSERT((mod & -4) == 0);
    buf_[0] = mod << 6 | (rm.code() & 0x7);
    // Set REX.B to the high bit of rm.code().
    rex_ |= (rm.code() >> 3);
-  len_ = 1;
  }


@@ -193,19 +212,21 @@
    len_ = 2;
  }

+void Operand::set_disp8(int disp) {
+  ASSERT(is_int8(disp));
+  ASSERT(len_ == 1 || len_ == 2);
+  int8_t* p = reinterpret_cast<int8_t*>(&buf_[len_]);
+  *p = disp;
+  len_ += sizeof(int8_t);
+}

-void Operand::set_disp32(int32_t disp) {
+void Operand::set_disp32(int disp) {
    ASSERT(len_ == 1 || len_ == 2);
    int32_t* p = reinterpret_cast<int32_t*>(&buf_[len_]);
    *p = disp;
    len_ += sizeof(int32_t);
  }

-
-Operand::Operand(Register reg) {
-  // reg
-  set_modrm(3, reg);
-}

  } }  // namespace v8::internal


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      Wed May 27 01:15:31 2009
@@ -253,143 +253,44 @@

  class Operand BASE_EMBEDDED {
   public:
-  // reg
-  INLINE(explicit Operand(Register reg));
-
-  // MemoryOperand
-  INLINE(explicit Operand()) { UNIMPLEMENTED(); }
-
-  // Returns true if this Operand is a wrapper for the specified register.
-  bool is_reg(Register reg) const;
-
-  // These constructors have been moved to MemOperand, and should
-  // be removed from Operand as soon as all their uses use MemOperands  
instead.
-    // [disp/r]
-  INLINE(explicit Operand(intptr_t disp, RelocInfo::Mode rmode)) {
-    UNIMPLEMENTED();
-  }
-  // disp only must always be relocated
-
    // [base + disp/r]
-  explicit Operand(Register base, int32_t disp,
-                   RelocInfo::Mode rmode = RelocInfo::NONE);
+  INLINE(Operand(Register base, int32_t disp));

    // [base + index*scale + disp/r]
-  explicit Operand(Register base,
-                   Register index,
-                   ScaleFactor scale,
-                   int32_t disp,
-                   RelocInfo::Mode rmode = RelocInfo::NONE);
+  Operand(Register base,
+          Register index,
+          ScaleFactor scale,
+          int32_t disp);

    // [index*scale + disp/r]
-  explicit Operand(Register index,
-                   ScaleFactor scale,
-                   int32_t disp,
-                   RelocInfo::Mode rmode = RelocInfo::NONE);
-
-  // End of constructors and methods that have been moved to MemOperand.
+  Operand(Register index,
+          ScaleFactor scale,
+          int32_t disp);

   private:
    byte rex_;
    byte buf_[10];
    // The number of bytes in buf_.
    unsigned int len_;
-  // Only valid if len_ > 4.
    RelocInfo::Mode rmode_;

    // Set the ModRM byte without an encoded 'reg' register. The
    // register is encoded later as part of the emit_operand operation.
+  // set_modrm can be called before or after set_sib and set_disp*.
    inline void set_modrm(int mod, Register rm);

+  // Set the SIB byte if one is needed. Sets the length to 2 rather than 1.
    inline void set_sib(ScaleFactor scale, Register index, Register base);
-  inline void set_disp8(int8_t disp);
-  inline void set_disp32(int32_t disp);
-
-  friend class Assembler;
-};
-
-class MemOperand : public Operand {
- public:
-  // [disp/r]
-  INLINE(explicit MemOperand(int32_t disp, RelocInfo::Mode rmode)) :
-      Operand() {
-    UNIMPLEMENTED();
-  }
-  // disp only must always be relocated
-
-  // [base + disp/r]
-  explicit MemOperand(Register base, int32_t disp,
-                   RelocInfo::Mode rmode = RelocInfo::NONE);
-
-  // [base + index*scale + disp/r]
-  explicit MemOperand(Register base,
-                   Register index,
-                   ScaleFactor scale,
-                   int32_t disp,
-                   RelocInfo::Mode rmode = RelocInfo::NONE);
-
-  // [index*scale + disp/r]
-  explicit MemOperand(Register index,
-                   ScaleFactor scale,
-                   int32_t disp,
-                   RelocInfo::Mode rmode = RelocInfo::NONE);
-};
-
-//  
-----------------------------------------------------------------------------
-// A Displacement describes the 32bit immediate field of an instruction  
which
-// may be used together with a Label in order to refer to a yet unknown  
code
-// position. Displacements stored in the instruction stream are used to  
describe
-// the instruction and to chain a list of instructions using the same  
Label.
-// A Displacement contains 2 different fields:
-//
-// next field: position of next displacement in the chain (0 = end of list)
-// type field: instruction type
-//
-// A next value of null (0) indicates the end of a chain (note that there  
can
-// be no displacement at position zero, because there is always at least  
one
-// instruction byte before the displacement).
-//
-// Displacement _data field layout
-//
-// |31.....2|1......0|
-// [  next  |  type  |
-
-class Displacement BASE_EMBEDDED {
- public:
-  enum Type {
-    UNCONDITIONAL_JUMP,
-    CODE_RELATIVE,
-    OTHER
-  };
-
-  int data() const { return data_; }
-  Type type() const { return TypeField::decode(data_); }
-  void next(Label* L) const {
-    int n = NextField::decode(data_);
-    n > 0 ? L->link_to(n) : L->Unuse();
-  }
-  void link_to(Label* L) { init(L, type()); }
-
-  explicit Displacement(int data) { data_ = data; }

-  Displacement(Label* L, Type type) { init(L, type); }
+  // Adds operand displacement fields (offsets added to the memory  
address).
+  // Needs to be called after set_sib, not before it.
+  inline void set_disp8(int disp);
+  inline void set_disp32(int disp);

-  void print() {
-    PrintF("%s (%x) ", (type() == UNCONDITIONAL_JUMP ? "jmp" : "[other]"),
-                       NextField::decode(data_));
-  }
-
- private:
-  int data_;
-
-  class TypeField: public BitField<Type, 0, 2> {};
-  class NextField: public BitField<int,  2, 32-2> {};
-
-  void init(Label* L, Type type);
+  friend class Assembler;
  };


-
  // CpuFeatures keeps track of which features are supported by the target  
CPU.
  // Supported features must be enabled by a Scope before use.
  // Example:
@@ -849,11 +750,6 @@
    void print(Label* L);
    void bind_to(Label* L, int pos);
    void link_to(Label* L, Label* appendix);
-
-  // displacements
-  inline Displacement disp_at(Label* L);
-  inline void disp_at_put(Label* L, Displacement disp);
-  inline void emit_disp(Label* L, Displacement::Type type);

    // record reloc info for current pc_
    void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);

Modified: branches/bleeding_edge/test/cctest/test-assembler-x64.cc
==============================================================================
--- branches/bleeding_edge/test/cctest/test-assembler-x64.cc    (original)
+++ branches/bleeding_edge/test/cctest/test-assembler-x64.cc    Wed May 27  
01:15:31 2009
@@ -153,11 +153,11 @@
    __ push(rsi);  // Value at (rbp - 8)
    __ push(rsi);  // Value at (rbp - 16)
    __ push(rdi);  // Value at (rbp - 24)
-  // const int kStackElementSize = 8;
-  //  __ mov(rax, Operand(rbp,-3 * kStackElementSize));
-  __ pop(rax);
-  __ pop(rax);
-  __ pop(rax);
+  const int kStackElementSize = 8;
+  __ mov(rax, Operand(rbp, -3 * kStackElementSize));
+  __ pop(rsi);
+  __ pop(rsi);
+  __ pop(rsi);
    __ pop(rbp);
    __ nop();
    __ ret(0);
@@ -166,7 +166,7 @@
    assm.GetCode(&desc);
    // Call the function from C++.
    int result =  FUNCTION_CAST<F2>(buffer)(3, 2);
-  CHECK_EQ(2, result);
+  CHECK_EQ(3, result);
  }

  TEST(AssemblerX64ControlFlow) {

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

Reply via email to