Revision: 20329
Author:   [email protected]
Date:     Fri Mar 28 11:13:14 2014 UTC
Log:      Refactor the arithmetic instructions for x64

[email protected]

Review URL: https://codereview.chromium.org/214753002
http://code.google.com/p/v8/source/detail?r=20329

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

=======================================
--- /branches/bleeding_edge/src/x64/assembler-x64.cc Fri Mar 28 04:55:00 2014 UTC +++ /branches/bleeding_edge/src/x64/assembler-x64.cc Fri Mar 28 11:13:14 2014 UTC
@@ -467,24 +467,30 @@

 // Assembler Instruction implementations.

-void Assembler::arithmetic_op(byte opcode, Register reg, const Operand& op) {
+void Assembler::arithmetic_op(byte opcode,
+                              Register reg,
+                              const Operand& op,
+                              int size) {
   EnsureSpace ensure_space(this);
-  emit_rex_64(reg, op);
+  emit_rex(reg, op, size);
   emit(opcode);
   emit_operand(reg, op);
 }


-void Assembler::arithmetic_op(byte opcode, Register reg, Register rm_reg) {
+void Assembler::arithmetic_op(byte opcode,
+                              Register reg,
+                              Register rm_reg,
+                              int size) {
   EnsureSpace ensure_space(this);
   ASSERT((opcode & 0xC6) == 2);
   if (rm_reg.low_bits() == 4)  {  // Forces SIB byte.
     // Swap reg and rm_reg and change opcode operand order.
-    emit_rex_64(rm_reg, reg);
+    emit_rex(rm_reg, reg, size);
     emit(opcode ^ 0x02);
     emit_modrm(rm_reg, reg);
   } else {
-    emit_rex_64(reg, rm_reg);
+    emit_rex(reg, rm_reg, size);
     emit(opcode);
     emit_modrm(reg, rm_reg);
   }
@@ -520,37 +526,45 @@
 }


-void Assembler::arithmetic_op_32(byte opcode, Register reg, Register rm_reg) { +void Assembler::arithmetic_op_8(byte opcode, Register reg, const Operand& op) {
   EnsureSpace ensure_space(this);
+  if (!reg.is_byte_register()) {
+    // Register is not one of al, bl, cl, dl.  Its encoding needs REX.
+    emit_rex_32(reg);
+  }
+  emit(opcode);
+  emit_operand(reg, op);
+}
+
+
+void Assembler::arithmetic_op_8(byte opcode, Register reg, Register rm_reg) {
+  EnsureSpace ensure_space(this);
   ASSERT((opcode & 0xC6) == 2);
-  if (rm_reg.low_bits() == 4) {  // Forces SIB byte.
+  if (rm_reg.low_bits() == 4)  {  // Forces SIB byte.
     // Swap reg and rm_reg and change opcode operand order.
-    emit_optional_rex_32(rm_reg, reg);
-    emit(opcode ^ 0x02);  // E.g. 0x03 -> 0x01 for ADD.
+    if (!rm_reg.is_byte_register() || !reg.is_byte_register()) {
+      // Register is not one of al, bl, cl, dl.  Its encoding needs REX.
+      emit_rex_32(rm_reg, reg);
+    }
+    emit(opcode ^ 0x02);
     emit_modrm(rm_reg, reg);
   } else {
-    emit_optional_rex_32(reg, rm_reg);
+    if (!reg.is_byte_register() || !rm_reg.is_byte_register()) {
+      // Register is not one of al, bl, cl, dl.  Its encoding needs REX.
+      emit_rex_32(reg, rm_reg);
+    }
     emit(opcode);
     emit_modrm(reg, rm_reg);
   }
 }
-
-
-void Assembler::arithmetic_op_32(byte opcode,
-                                 Register reg,
-                                 const Operand& rm_reg) {
-  EnsureSpace ensure_space(this);
-  emit_optional_rex_32(reg, rm_reg);
-  emit(opcode);
-  emit_operand(reg, rm_reg);
-}


 void Assembler::immediate_arithmetic_op(byte subcode,
                                         Register dst,
-                                        Immediate src) {
+                                        Immediate src,
+                                        int size) {
   EnsureSpace ensure_space(this);
-  emit_rex_64(dst);
+  emit_rex(dst, size);
   if (is_int8(src.value_)) {
     emit(0x83);
     emit_modrm(subcode, dst);
@@ -567,9 +581,10 @@

 void Assembler::immediate_arithmetic_op(byte subcode,
                                         const Operand& dst,
-                                        Immediate src) {
+                                        Immediate src,
+                                        int size) {
   EnsureSpace ensure_space(this);
-  emit_rex_64(dst);
+  emit_rex(dst, size);
   if (is_int8(src.value_)) {
     emit(0x83);
     emit_operand(subcode, dst);
@@ -619,43 +634,6 @@
     emitw(src.value_);
   }
 }
-
-
-void Assembler::immediate_arithmetic_op_32(byte subcode,
-                                           Register dst,
-                                           Immediate src) {
-  EnsureSpace ensure_space(this);
-  emit_optional_rex_32(dst);
-  if (is_int8(src.value_)) {
-    emit(0x83);
-    emit_modrm(subcode, dst);
-    emit(src.value_);
-  } else if (dst.is(rax)) {
-    emit(0x05 | (subcode << 3));
-    emitl(src.value_);
-  } else {
-    emit(0x81);
-    emit_modrm(subcode, dst);
-    emitl(src.value_);
-  }
-}
-
-
-void Assembler::immediate_arithmetic_op_32(byte subcode,
-                                           const Operand& dst,
-                                           Immediate src) {
-  EnsureSpace ensure_space(this);
-  emit_optional_rex_32(dst);
-  if (is_int8(src.value_)) {
-    emit(0x83);
-    emit_operand(subcode, dst);
-    emit(src.value_);
-  } else {
-    emit(0x81);
-    emit_operand(subcode, dst);
-    emitl(src.value_);
-  }
-}


 void Assembler::immediate_arithmetic_op_8(byte subcode,
@@ -675,8 +653,8 @@
                                           Immediate src) {
   EnsureSpace ensure_space(this);
   if (!dst.is_byte_register()) {
-    // Use 64-bit mode byte registers.
-    emit_rex_64(dst);
+    // Register is not one of al, bl, cl, dl.  Its encoding needs REX.
+    emit_rex_32(dst);
   }
   ASSERT(is_int8(src.value_) || is_uint8(src.value_));
   emit(0x80);
=======================================
--- /branches/bleeding_edge/src/x64/assembler-x64.h Fri Mar 28 04:55:00 2014 UTC +++ /branches/bleeding_edge/src/x64/assembler-x64.h Fri Mar 28 11:13:14 2014 UTC
@@ -692,6 +692,8 @@
   // - Instructions on 64-bit (quadword) operands/registers use 'q'.
   // - Instructions on operands/registers with pointer size use 'p'.

+  STATIC_ASSERT(kPointerSize == kInt64Size || kPointerSize == kInt32Size);
+
 #define DECLARE_INSTRUCTION(instruction)                \
   template<class P1>                                    \
   void instruction##p(P1 p1) {                          \
@@ -818,15 +820,15 @@
   void cmpb_al(Immediate src);

   void cmpb(Register dst, Register src) {
-    arithmetic_op(0x3A, dst, src);
+    arithmetic_op_8(0x3A, dst, src);
   }

   void cmpb(Register dst, const Operand& src) {
-    arithmetic_op(0x3A, dst, src);
+    arithmetic_op_8(0x3A, dst, src);
   }

   void cmpb(const Operand& dst, Register src) {
-    arithmetic_op(0x38, src, dst);
+    arithmetic_op_8(0x38, src, dst);
   }

   void cmpb(const Operand& dst, Immediate src) {
@@ -1382,14 +1384,16 @@
   // AND, OR, XOR, or CMP.  The encodings of these operations are all
   // similar, differing just in the opcode or in the reg field of the
   // ModR/M byte.
+  void arithmetic_op_8(byte opcode, Register reg, Register rm_reg);
+  void arithmetic_op_8(byte opcode, Register reg, const Operand& rm_reg);
   void arithmetic_op_16(byte opcode, Register reg, Register rm_reg);
   void arithmetic_op_16(byte opcode, Register reg, const Operand& rm_reg);
-  void arithmetic_op_32(byte opcode, Register reg, Register rm_reg);
-  void arithmetic_op_32(byte opcode, Register reg, const Operand& rm_reg);
-  void arithmetic_op(byte opcode, Register reg, Register rm_reg);
-  void arithmetic_op(byte opcode, Register reg, const Operand& rm_reg);
-  void immediate_arithmetic_op(byte subcode, Register dst, Immediate src);
- void immediate_arithmetic_op(byte subcode, const Operand& dst, Immediate src); + // Operate on operands/registers with pointer size, 32-bit or 64-bit size.
+  void arithmetic_op(byte opcode, Register reg, Register rm_reg, int size);
+  void arithmetic_op(byte opcode,
+                     Register reg,
+                     const Operand& rm_reg,
+                     int size);
   // Operate on a byte in memory or register.
   void immediate_arithmetic_op_8(byte subcode,
                                  Register dst,
@@ -1404,13 +1408,15 @@
   void immediate_arithmetic_op_16(byte subcode,
                                   const Operand& dst,
                                   Immediate src);
-  // Operate on a 32-bit word in memory or register.
-  void immediate_arithmetic_op_32(byte subcode,
-                                  Register dst,
-                                  Immediate src);
-  void immediate_arithmetic_op_32(byte subcode,
-                                  const Operand& dst,
-                                  Immediate src);
+ // Operate on operands/registers with pointer size, 32-bit or 64-bit size.
+  void immediate_arithmetic_op(byte subcode,
+                               Register dst,
+                               Immediate src,
+                               int size);
+  void immediate_arithmetic_op(byte subcode,
+                               const Operand& dst,
+                               Immediate src,
+                               int size);

   // Emit machine code for a shift operation.
   void shift(Register dst, Immediate shift_amount, int subcode, int size);
@@ -1428,138 +1434,63 @@

   // Arithmetics
   void emit_add(Register dst, Register src, int size) {
-    if (size == kInt64Size) {
-      arithmetic_op(0x03, dst, src);
-    } else {
-      ASSERT(size == kInt32Size);
-      arithmetic_op_32(0x03, dst, src);
-    }
+    arithmetic_op(0x03, dst, src, size);
   }

   void emit_add(Register dst, Immediate src, int size) {
-    if (size == kInt64Size) {
-      immediate_arithmetic_op(0x0, dst, src);
-    } else {
-      ASSERT(size == kInt32Size);
-      immediate_arithmetic_op_32(0x0, dst, src);
-    }
+    immediate_arithmetic_op(0x0, dst, src, size);
   }

   void emit_add(Register dst, const Operand& src, int size) {
-    if (size == kInt64Size) {
-      arithmetic_op(0x03, dst, src);
-    } else {
-      ASSERT(size == kInt32Size);
-      arithmetic_op_32(0x03, dst, src);
-    }
+    arithmetic_op(0x03, dst, src, size);
   }

   void emit_add(const Operand& dst, Register src, int size) {
-    if (size == kInt64Size) {
-      arithmetic_op(0x1, src, dst);
-    } else {
-      ASSERT(size == kInt32Size);
-      arithmetic_op_32(0x1, src, dst);
-    }
+    arithmetic_op(0x1, src, dst, size);
   }

   void emit_add(const Operand& dst, Immediate src, int size) {
-    if (size == kInt64Size) {
-      immediate_arithmetic_op(0x0, dst, src);
-    } else {
-      ASSERT(size == kInt32Size);
-      immediate_arithmetic_op_32(0x0, dst, src);
-    }
+    immediate_arithmetic_op(0x0, dst, src, size);
   }

   void emit_and(Register dst, Register src, int size) {
-    if (size == kInt64Size) {
-      arithmetic_op(0x23, dst, src);
-    } else {
-      ASSERT(size == kInt32Size);
-      arithmetic_op_32(0x23, dst, src);
-    }
+    arithmetic_op(0x23, dst, src, size);
   }

   void emit_and(Register dst, const Operand& src, int size) {
-    if (size == kInt64Size) {
-      arithmetic_op(0x23, dst, src);
-    } else {
-      ASSERT(size == kInt32Size);
-      arithmetic_op_32(0x23, dst, src);
-    }
+    arithmetic_op(0x23, dst, src, size);
   }

   void emit_and(const Operand& dst, Register src, int size) {
-    if (size == kInt64Size) {
-      arithmetic_op(0x21, src, dst);
-    } else {
-      ASSERT(size == kInt32Size);
-      arithmetic_op_32(0x21, src, dst);
-    }
+    arithmetic_op(0x21, src, dst, size);
   }

   void emit_and(Register dst, Immediate src, int size) {
-    if (size == kInt64Size) {
-      immediate_arithmetic_op(0x4, dst, src);
-    } else {
-      ASSERT(size == kInt32Size);
-      immediate_arithmetic_op_32(0x4, dst, src);
-    }
+    immediate_arithmetic_op(0x4, dst, src, size);
   }

   void emit_and(const Operand& dst, Immediate src, int size) {
-    if (size == kInt64Size) {
-      immediate_arithmetic_op(0x4, dst, src);
-    } else {
-      ASSERT(size == kInt32Size);
-      immediate_arithmetic_op_32(0x4, dst, src);
-    }
+    immediate_arithmetic_op(0x4, dst, src, size);
   }

   void emit_cmp(Register dst, Register src, int size) {
-    if (size == kInt64Size) {
-      arithmetic_op(0x3B, dst, src);
-    } else {
-      ASSERT(size == kInt32Size);
-      arithmetic_op_32(0x3B, dst, src);
-    }
+    arithmetic_op(0x3B, dst, src, size);
   }

   void emit_cmp(Register dst, const Operand& src, int size) {
-    if (size == kInt64Size) {
-      arithmetic_op(0x3B, dst, src);
-    } else {
-      ASSERT(size == kInt32Size);
-      arithmetic_op_32(0x3B, dst, src);
-    }
+    arithmetic_op(0x3B, dst, src, size);
   }

   void emit_cmp(const Operand& dst, Register src, int size) {
-    if (size == kInt64Size) {
-      arithmetic_op(0x39, src, dst);
-    } else {
-      ASSERT(size == kInt32Size);
-      arithmetic_op_32(0x39, src, dst);
-    }
+    arithmetic_op(0x39, src, dst, size);
   }

   void emit_cmp(Register dst, Immediate src, int size) {
-    if (size == kInt64Size) {
-      immediate_arithmetic_op(0x7, dst, src);
-    } else {
-      ASSERT(size == kInt32Size);
-      immediate_arithmetic_op_32(0x7, dst, src);
-    }
+    immediate_arithmetic_op(0x7, dst, src, size);
   }

   void emit_cmp(const Operand& dst, Immediate src, int size) {
-    if (size == kInt64Size) {
-      immediate_arithmetic_op(0x7, dst, src);
-    } else {
-      ASSERT(size == kInt32Size);
-      immediate_arithmetic_op_32(0x7, dst, src);
-    }
+    immediate_arithmetic_op(0x7, dst, src, size);
   }

   void emit_dec(Register dst, int size);
@@ -1599,99 +1530,49 @@
   void emit_not(const Operand& dst, int size);

   void emit_or(Register dst, Register src, int size) {
-    if (size == kInt64Size) {
-      arithmetic_op(0x0B, dst, src);
-    } else {
-      arithmetic_op_32(0x0B, dst, src);
-    }
+    arithmetic_op(0x0B, dst, src, size);
   }

   void emit_or(Register dst, const Operand& src, int size) {
-    if (size == kInt64Size) {
-      arithmetic_op(0x0B, dst, src);
-    } else {
-      arithmetic_op_32(0x0B, dst, src);
-    }
+    arithmetic_op(0x0B, dst, src, size);
   }

   void emit_or(const Operand& dst, Register src, int size) {
-    if (size == kInt64Size) {
-      arithmetic_op(0x9, src, dst);
-    } else {
-      arithmetic_op_32(0x9, src, dst);
-    }
+    arithmetic_op(0x9, src, dst, size);
   }

   void emit_or(Register dst, Immediate src, int size) {
-    if (size == kInt64Size) {
-      immediate_arithmetic_op(0x1, dst, src);
-    } else {
-      immediate_arithmetic_op_32(0x1, dst, src);
-    }
+    immediate_arithmetic_op(0x1, dst, src, size);
   }

   void emit_or(const Operand& dst, Immediate src, int size) {
-    if (size == kInt64Size) {
-      immediate_arithmetic_op(0x1, dst, src);
-    } else {
-      immediate_arithmetic_op_32(0x1, dst, src);
-    }
+    immediate_arithmetic_op(0x1, dst, src, size);
   }

   void emit_repmovs(int size);

   void emit_sbb(Register dst, Register src, int size) {
-    if (size == kInt64Size) {
-      arithmetic_op(0x1b, dst, src);
-    } else {
-      ASSERT(size == kInt32Size);
-      arithmetic_op_32(0x1b, dst, src);
-    }
+    arithmetic_op(0x1b, dst, src, size);
   }

   void emit_sub(Register dst, Register src, int size) {
-    if (size == kInt64Size) {
-      arithmetic_op(0x2B, dst, src);
-    } else {
-      ASSERT(size == kInt32Size);
-      arithmetic_op_32(0x2B, dst, src);
-    }
+    arithmetic_op(0x2B, dst, src, size);
   }

   void emit_sub(Register dst, Immediate src, int size) {
-    if (size == kInt64Size) {
-      immediate_arithmetic_op(0x5, dst, src);
-    } else {
-      ASSERT(size == kInt32Size);
-      immediate_arithmetic_op_32(0x5, dst, src);
-    }
+    immediate_arithmetic_op(0x5, dst, src, size);
   }

   void emit_sub(Register dst, const Operand& src, int size) {
-    if (size == kInt64Size) {
-      arithmetic_op(0x2B, dst, src);
-    } else {
-      ASSERT(size == kInt32Size);
-      arithmetic_op_32(0x2B, dst, src);
-    }
+    arithmetic_op(0x2B, dst, src, size);
   }

   void emit_sub(const Operand& dst, Register src, int size) {
-    if (size == kInt64Size) {
-      arithmetic_op(0x29, src, dst);
-    } else {
-      ASSERT(size == kInt32Size);
-      arithmetic_op_32(0x29, src, dst);
-    }
+    arithmetic_op(0x29, src, dst, size);
   }

   void emit_sub(const Operand& dst, Immediate src, int size) {
-    if (size == kInt64Size) {
-      immediate_arithmetic_op(0x5, dst, src);
-    } else {
-      ASSERT(size == kInt32Size);
-      immediate_arithmetic_op_32(0x5, dst, src);
-    }
+    immediate_arithmetic_op(0x5, dst, src, size);
   }

   void emit_test(Register dst, Register src, int size);
@@ -1703,52 +1584,29 @@
   void emit_xchg(Register dst, Register src, int size);

   void emit_xor(Register dst, Register src, int size) {
-    if (size == kInt64Size) {
-      if (dst.code() == src.code()) {
-        arithmetic_op_32(0x33, dst, src);
-      } else {
-        arithmetic_op(0x33, dst, src);
-      }
+    if (size == kInt64Size && dst.code() == src.code()) {
+ // 32 bit operations zero the top 32 bits of 64 bit registers. Therefore
+    // there is no need to make this a 64 bit operation.
+      arithmetic_op(0x33, dst, src, kInt32Size);
     } else {
-      ASSERT(size == kInt32Size);
-      arithmetic_op_32(0x33, dst, src);
+      arithmetic_op(0x33, dst, src, size);
     }
   }

   void emit_xor(Register dst, const Operand& src, int size) {
-    if (size == kInt64Size) {
-      arithmetic_op(0x33, dst, src);
-    } else {
-      ASSERT(size == kInt32Size);
-      arithmetic_op_32(0x33, dst, src);
-    }
+    arithmetic_op(0x33, dst, src, size);
   }

   void emit_xor(Register dst, Immediate src, int size) {
-    if (size == kInt64Size) {
-      immediate_arithmetic_op(0x6, dst, src);
-    } else {
-      ASSERT(size == kInt32Size);
-      immediate_arithmetic_op_32(0x6, dst, src);
-    }
+    immediate_arithmetic_op(0x6, dst, src, size);
   }

   void emit_xor(const Operand& dst, Immediate src, int size) {
-    if (size == kInt64Size) {
-      immediate_arithmetic_op(0x6, dst, src);
-    } else {
-      ASSERT(size == kInt32Size);
-      immediate_arithmetic_op_32(0x6, dst, src);
-    }
+    immediate_arithmetic_op(0x6, dst, src, size);
   }

   void emit_xor(const Operand& dst, Register src, int size) {
-    if (size == kInt64Size) {
-      arithmetic_op(0x31, src, dst);
-    } else {
-      ASSERT(size == kInt32Size);
-      arithmetic_op_32(0x31, src, dst);
-    }
+    arithmetic_op(0x31, src, dst, size);
   }

   friend class CodePatcher;
=======================================
--- /branches/bleeding_edge/test/cctest/test-assembler-x64.cc Fri Mar 28 04:55:00 2014 UTC +++ /branches/bleeding_edge/test/cctest/test-assembler-x64.cc Fri Mar 28 11:13:14 2014 UTC
@@ -139,6 +139,37 @@
   int result =  FUNCTION_CAST<F2>(buffer)(3, 2);
   CHECK_EQ(5, result);
 }
+
+
+TEST(AssemblerX64CmpbOperation) {
+  // Allocate an executable page of memory.
+  size_t actual_size;
+ byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
+                                                 &actual_size,
+                                                 true));
+  CHECK(buffer);
+ Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
+
+ // Assemble a function that compare argument byte returing 1 if equal else 0. + // On Windows, it compares rcx with rdx which does not require REX prefix;
+  // on Linux, it compares rdi with rsi which requires REX prefix.
+
+  Label done;
+  __ movq(rax, Immediate(1));
+  __ cmpb(arg1, arg2);
+  __ j(equal, &done);
+  __ movq(rax, Immediate(0));
+  __ bind(&done);
+  __ ret(0);
+
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  // Call the function from C++.
+  int result =  FUNCTION_CAST<F2>(buffer)(0x1002, 0x2002);
+  CHECK_EQ(1, result);
+  result =  FUNCTION_CAST<F2>(buffer)(0x1002, 0x2003);
+  CHECK_EQ(0, result);
+}


 TEST(AssemblerX64ImulOperation) {

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to