Author: [email protected]
Date: Tue Jun  2 00:21:05 2009
New Revision: 2085

Modified:
    branches/bleeding_edge/src/assembler.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:
X64: Added jmp and call and nop(n) to X64 assembler.

Review URL: http://codereview.chromium.org/115920


Modified: branches/bleeding_edge/src/assembler.h
==============================================================================
--- branches/bleeding_edge/src/assembler.h      (original)
+++ branches/bleeding_edge/src/assembler.h      Tue Jun  2 00:21:05 2009
@@ -437,6 +437,7 @@
    return (x & -(1 << n)) == 0;
  }

+static inline bool is_uint2(int x)  { return is_uintn(x, 2); }
  static inline bool is_uint3(int x)  { return is_uintn(x, 3); }
  static inline bool is_uint4(int x)  { return is_uintn(x, 4); }
  static inline bool is_uint5(int x)  { return is_uintn(x, 5); }

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 00:21:05  
2009
@@ -70,8 +70,23 @@
  }


+// 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());
+  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 is set.  REX.X is cleared.
+// 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);
  }
@@ -222,7 +237,7 @@
    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);
+    set_sib(kTimes1, rsp, base);
    }

    if (disp == 0 && !base.is(rbp) && !base.is(r13)) {
@@ -246,7 +261,7 @@

  void Operand::set_sib(ScaleFactor scale, Register index, Register base) {
    ASSERT(len_ == 1);
-  ASSERT((scale & -4) == 0);
+  ASSERT(is_uint2(scale));
    // Use SIB with no index register only for base rsp or r12.
    ASSERT(!index.is(rsp) || base.is(rsp) || base.is(r12));
    buf_[1] = scale << 6 | (index.code() & 0x7) << 3 | (base.code() & 0x7);

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 00:21:05 2009
@@ -271,12 +271,13 @@
  }


-void Assembler::emit_operand(Register reg, const Operand& adr) {
+void Assembler::emit_operand(int rm, const Operand& adr) {
+  ASSERT_EQ(rm & 0x07, rm);
    const unsigned length = adr.len_;
    ASSERT(length > 0);

    // Emit updated ModRM byte containing the given register.
-  pc_[0] = (adr.buf_[0] & ~0x38) | ((reg.code() && 0x7) << 3);
+  pc_[0] = (adr.buf_[0] & ~0x38) | (rm << 3);

    // Emit the rest of the encoded operand.
    for (unsigned i = 1; i < length; i++) pc_[i] = adr.buf_[i];
@@ -362,6 +363,18 @@
  }


+void Assembler::call(Register adr) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  // Opcode: FF /2 r64
+  if (!is_uint3(adr.code())) {
+    emit_rex_64(adr);
+  }
+  emit(0xFF);
+  emit(0xD0 | (adr.code() & 0x07));
+}
+
+
  void Assembler::dec(Register dst) {
    EnsureSpace ensure_space(this);
    last_pc_ = pc_;
@@ -479,6 +492,18 @@
  }


+void Assembler::jmp(Register target) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  // Opcode FF/4 r64
+  if (!is_uint3(target.code())) {
+    emit_rex_64(target);
+  }
+  emit(0xFF);
+  emit(0xE0 | target.code() & 0x07);
+}
+
+
  void Assembler::movq(Register dst, const Operand& src) {
    EnsureSpace ensure_space(this);
    last_pc_ = pc_;
@@ -556,6 +581,93 @@
    emit_rex_64(dst);
    emit(0xF7);
    emit_operand(2, dst);
+}
+
+
+void Assembler::nop(int n) {
+  // The recommended muti-byte sequences of NOP instructions from the  
Intel 64
+  // and IA-32 Architectures Software Developer's Manual.
+  //
+  // Length   Assembly                                Byte Sequence
+  // 2 bytes  66 NOP                                  66 90H
+  // 3 bytes  NOP DWORD ptr [EAX]                     0F 1F 00H
+  // 4 bytes  NOP DWORD ptr [EAX + 00H]               0F 1F 40 00H
+  // 5 bytes  NOP DWORD ptr [EAX + EAX*1 + 00H]       0F 1F 44 00 00H
+  // 6 bytes  66 NOP DWORD ptr [EAX + EAX*1 + 00H]    66 0F 1F 44 00 00H
+  // 7 bytes  NOP DWORD ptr [EAX + 00000000H]         0F 1F 80 00 00 00 00H
+  // 8 bytes  NOP DWORD ptr [EAX + EAX*1 + 00000000H] 0F 1F 84 00 00 00 00  
00H
+  // 9 bytes  66 NOP DWORD ptr [EAX + EAX*1 +         66 0F 1F 84 00 00 00  
00
+  //          00000000H]                              00H
+
+  ASSERT(1 <= n);
+  ASSERT(n <= 9);
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  switch (n) {
+  case 1:
+    emit(0x90);
+    return;
+  case 2:
+    emit(0x66);
+    emit(0x90);
+    return;
+  case 3:
+    emit(0x0f);
+    emit(0x1f);
+    emit(0x00);
+    return;
+  case 4:
+    emit(0x0f);
+    emit(0x1f);
+    emit(0x40);
+    emit(0x00);
+    return;
+  case 5:
+    emit(0x0f);
+    emit(0x1f);
+    emit(0x44);
+    emit(0x00);
+    emit(0x00);
+    return;
+  case 6:
+    emit(0x66);
+    emit(0x0f);
+    emit(0x1f);
+    emit(0x44);
+    emit(0x00);
+    emit(0x00);
+    return;
+  case 7:
+    emit(0x0f);
+    emit(0x1f);
+    emit(0x80);
+    emit(0x00);
+    emit(0x00);
+    emit(0x00);
+    emit(0x00);
+    return;
+  case 8:
+    emit(0x0f);
+    emit(0x1f);
+    emit(0x84);
+    emit(0x00);
+    emit(0x00);
+    emit(0x00);
+    emit(0x00);
+    emit(0x00);
+    return;
+  case 9:
+    emit(0x66);
+    emit(0x0f);
+    emit(0x1f);
+    emit(0x84);
+    emit(0x00);
+    emit(0x00);
+    emit(0x00);
+    emit(0x00);
+    emit(0x00);
+    return;
+  }
  }



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 00:21:05 2009
@@ -225,10 +225,12 @@
  // Machine instruction Operands

  enum ScaleFactor {
-  times_1 = 0,
-  times_2 = 1,
-  times_4 = 2,
-  times_8 = 3
+  kTimes1 = 0,
+  kTimes2 = 1,
+  kTimes4 = 2,
+  kTimes8 = 3,
+  kTimesIntSize = kTimes4,
+  kTimesPointerSize = kTimes8
  };


@@ -626,6 +628,7 @@
    void hlt();
    void int3();
    void nop();
+  void nop(int n);
    void rdtsc();
    void ret(int imm16);

@@ -647,16 +650,18 @@
    void bind(Label* L);  // binds an unbound label L to the current code  
position

    // Calls
+  // Call near relative 32-bit displacement, relative to next instruction.
    void call(Label* L);
-  void call(byte* entry, RelocInfo::Mode rmode);
-  void call(const Operand& adr);
-  void call(Handle<Code> code, RelocInfo::Mode rmode);
+
+  // Call near absolute indirect, address in register
+  void call(Register adr);

    // Jumps
+  // Jump short or near relative.
    void jmp(Label* L);  // unconditional jump to L
-  void jmp(byte* entry, RelocInfo::Mode rmode);
-  void jmp(const Operand& adr);
-  void jmp(Handle<Code> code, RelocInfo::Mode rmode);
+
+  // Jump near absolute indirect (r64)
+  void jmp(Register adr);

    // Conditional jumps
    void j(Condition cc, Label* L);
@@ -815,7 +820,6 @@
    // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
    // REX.W is set.
    inline void emit_rex_64(Register reg, Register rm_reg);
-  void emit_rex_64(Register rm_reg) { emit_rex_64(rax, rm_reg); }

    // Emits a REX prefix that encodes a 64-bit operand size and
    // the top bit of the destination, index, and base register codes.
@@ -823,10 +827,22 @@
    // register is used for REX.B, and the high bit of op's index register
    // is used for REX.X.  REX.W is set.
    inline void emit_rex_64(Register reg, const Operand& op);
-  void emit_rex_64(const Operand& op) { emit_rex_64(rax, op); }
+
+  // Emits a REX prefix that encodes a 64-bit operand size and
+  // the top bit of the register code.
+  // The high bit of register is used for REX.B.
+  // REX.W is set and REX.R and REX.X are clear.
+  inline void emit_rex_64(Register rm_reg);
+
+  // Emits a REX prefix that encodes a 64-bit operand size and
+  // the top bit of the index and base register codes.
+  // 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.
+  inline void emit_rex_64(const Operand& op);

    // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
-  // REX.W is set.
+  // REX.W is clear.
    inline void emit_rex_32(Register reg, Register rm_reg);

    // The high bit of reg is used for REX.R, the high bit of op's base
@@ -848,10 +864,14 @@
    // 1- or 4-byte offset for a memory operand.  Also encodes
    // the second operand of the operation, a register or operation
    // subcode, into the Mod/RM byte.
-  void emit_operand(Register reg, const Operand& adr);
-  void emit_operand(int op_subcode, const Operand& adr) {
-    emit_operand(Register::toRegister(op_subcode), adr);
+  void emit_operand(Register reg, const Operand& adr) {
+    emit_operand(reg.code() & 0x07, adr);
    }
+
+  // Emit the Mod/RM byte, and optionally the SIB byte and
+  // 1- or 4-byte offset for a memory operand.  Also used to encode
+  // a three-byte opcode extension into the Mod/RM byte.
+  void emit_operand(int rm, const Operand& adr);

    // Emit the code-object-relative offset of the label's position
    inline void emit_code_relative_offset(Label* label);

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

Reply via email to