Add more arithmetic to x64 assembler.
authorwhesse@chromium.org <whesse@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 28 May 2009 10:06:48 +0000 (10:06 +0000)
committerwhesse@chromium.org <whesse@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 28 May 2009 10:06:48 +0000 (10:06 +0000)
Review URL: http://codereview.chromium.org/115857

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2070 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

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

index 04cdc7ce25e67c6dff0fd72f4459cd585d9777dd..94e3ec000984f08e403d29fd08c2ec97930e353e 100644 (file)
@@ -41,8 +41,6 @@ Condition NegateCondition(Condition cc) {
 // -----------------------------------------------------------------------------
 // Implementation of Assembler
 
-#define EMIT(x)                                 \
-  *pc_++ = (x)
 
 
 void Assembler::emitl(uint32_t x) {
@@ -60,7 +58,7 @@ void Assembler::emitq(uint64_t x, RelocInfo::Mode rmode) {
 // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
 // REX.W is set.
 void Assembler::emit_rex_64(Register reg, Register rm_reg) {
-  EMIT(0x48 | (reg.code() & 0x8) >> 1 | rm_reg.code() >> 3);
+  emit(0x48 | (reg.code() & 0x8) >> 1 | rm_reg.code() >> 3);
 }
 
 
@@ -68,7 +66,7 @@ void Assembler::emit_rex_64(Register reg, Register rm_reg) {
 // 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_);
+  emit(0x48 | (reg.code() & 0x8) >> 1 | op.rex_);
 }
 
 
@@ -82,8 +80,6 @@ byte* Assembler::target_address_at(byte* location) {
   return NULL;
 }
 
-#undef EMIT
-
 
 // -----------------------------------------------------------------------------
 // Implementation of RelocInfo
index cc266b465cc95e63fc0dbd11fcceb43633d42fc5..a8b1b8ed0df746a61079bc99cc5f97d4a0f4e5ce 100644 (file)
@@ -82,10 +82,6 @@ void CpuFeatures::Probe()  {
 // -----------------------------------------------------------------------------
 // Implementation of Assembler
 
-// Emit a single byte. Must always be inlined.
-#define EMIT(x)                                 \
-  *pc_++ = (x)
-
 #ifdef GENERATED_CODE_COVERAGE
 static void InitCoverageLog();
 #endif
@@ -305,7 +301,7 @@ void Assembler::arithmetic_op(byte opcode, Register reg, const Operand& op) {
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   emit_rex_64(reg, op);
-  EMIT(opcode);
+  emit(opcode);
   emit_operand(reg, op);
 }
 
@@ -314,8 +310,8 @@ void Assembler::arithmetic_op(byte opcode, Register dst, Register src) {
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   emit_rex_64(dst, src);
-  EMIT(opcode);
-  EMIT(0xC0 | (dst.code() & 0x7) << 3 | (src.code() & 0x7));
+  emit(opcode);
+  emit(0xC0 | (dst.code() & 0x7) << 3 | (src.code() & 0x7));
 }
 
 void Assembler::immediate_arithmetic_op(byte subcode,
@@ -325,12 +321,12 @@ void Assembler::immediate_arithmetic_op(byte subcode,
   last_pc_ = pc_;
   emit_rex_64(rax, dst);
   if (is_int8(src.value_)) {
-    EMIT(0x83);
-    EMIT(0xC0 | (subcode << 3) | (dst.code() & 0x7));
-    EMIT(src.value_);
+    emit(0x83);
+    emit(0xC0 | (subcode << 3) | (dst.code() & 0x7));
+    emit(src.value_);
   } else {
-    EMIT(0x81);
-    EMIT(0xC0 | (subcode << 3) | (dst.code() & 0x7));
+    emit(0x81);
+    emit(0xC0 | (subcode << 3) | (dst.code() & 0x7));
     emitl(src.value_);
   }
 }
@@ -342,11 +338,11 @@ void Assembler::immediate_arithmetic_op(byte subcode,
   last_pc_ = pc_;
   emit_rex_64(rax, dst);
   if (is_int8(src.value_)) {
-    EMIT(0x83);
+    emit(0x83);
     emit_operand(Register::toRegister(subcode), dst);
-    EMIT(src.value_);
+    emit(src.value_);
   } else {
-    EMIT(0x81);
+    emit(0x81);
     emit_operand(Register::toRegister(subcode), dst);
     emitl(src.value_);
   }
@@ -357,7 +353,7 @@ void Assembler::call(Label* L) {
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   // 1110 1000 #32-bit disp
-  EMIT(0xE8);
+  emit(0xE8);
   if (L->is_bound()) {
     int offset = L->pos() - pc_offset() - sizeof(int32_t);
     ASSERT(offset <= 0);
@@ -378,8 +374,8 @@ void Assembler::dec(Register dst) {
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   emit_rex_64(rcx, dst);
-  EMIT(0xFF);
-  EMIT(0xC8 | (dst.code() & 0x7));
+  emit(0xFF);
+  emit(0xC8 | (dst.code() & 0x7));
 }
 
 
@@ -387,7 +383,7 @@ void Assembler::dec(const Operand& dst) {
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   emit_rex_64(rax, dst);
-  EMIT(0xFF);
+  emit(0xFF);
   emit_operand(rcx, dst);
 }
 
@@ -395,7 +391,7 @@ void Assembler::dec(const Operand& dst) {
 void Assembler::hlt() {
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
-  EMIT(0xF4);
+  emit(0xF4);
 }
 
 
@@ -403,8 +399,8 @@ void Assembler::inc(Register dst) {
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   emit_rex_64(rax, dst);
-  EMIT(0xFF);
-  EMIT(0xC0 | (dst.code() & 0x7));
+  emit(0xFF);
+  emit(0xC0 | (dst.code() & 0x7));
 }
 
 
@@ -412,7 +408,7 @@ void Assembler::inc(const Operand& dst) {
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   emit_rex_64(rax, dst);
-  EMIT(0xFF);
+  emit(0xFF);
   emit_operand(rax, dst);
 }
 
@@ -420,7 +416,7 @@ void Assembler::inc(const Operand& dst) {
 void Assembler::int3() {
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
-  EMIT(0xCC);
+  emit(0xCC);
 }
 
 
@@ -435,24 +431,24 @@ void Assembler::j(Condition cc, Label* L) {
     ASSERT(offs <= 0);
     if (is_int8(offs - short_size)) {
       // 0111 tttn #8-bit disp
-      EMIT(0x70 | cc);
-      EMIT((offs - short_size) & 0xFF);
+      emit(0x70 | cc);
+      emit((offs - short_size) & 0xFF);
     } else {
       // 0000 1111 1000 tttn #32-bit disp
-      EMIT(0x0F);
-      EMIT(0x80 | cc);
+      emit(0x0F);
+      emit(0x80 | cc);
       emitl(offs - long_size);
     }
   } else if (L->is_linked()) {
     // 0000 1111 1000 tttn #32-bit disp
-    EMIT(0x0F);
-    EMIT(0x80 | cc);
+    emit(0x0F);
+    emit(0x80 | cc);
     emitl(L->pos());
     L->link_to(pc_offset() - sizeof(int32_t));
   } else {
     ASSERT(L->is_unused());
-    EMIT(0x0F);
-    EMIT(0x80 | cc);
+    emit(0x0F);
+    emit(0x80 | cc);
     int32_t current = pc_offset();
     emitl(current);
     L->link_to(current);
@@ -468,22 +464,22 @@ void Assembler::jmp(Label* L) {
     ASSERT(offs <= 0);
     if (is_int8(offs - sizeof(int8_t))) {
       // 1110 1011 #8-bit disp
-      EMIT(0xEB);
-      EMIT((offs - sizeof(int8_t)) & 0xFF);
+      emit(0xEB);
+      emit((offs - sizeof(int8_t)) & 0xFF);
     } else {
       // 1110 1001 #32-bit disp
-      EMIT(0xE9);
+      emit(0xE9);
       emitl(offs - sizeof(int32_t));
     }
   } else  if (L->is_linked()) {
     // 1110 1001 #32-bit disp
-    EMIT(0xE9);
+    emit(0xE9);
     emitl(L->pos());
     L->link_to(pc_offset() - sizeof(int32_t));
   } else {
     // 1110 1001 #32-bit disp
     ASSERT(L->is_unused());
-    EMIT(0xE9);
+    emit(0xE9);
     int32_t current = pc_offset();
     emitl(current);
     L->link_to(current);
@@ -495,7 +491,7 @@ void Assembler::movq(Register dst, const Operand& src) {
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   emit_rex_64(dst, src);
-  EMIT(0x8B);
+  emit(0x8B);
   emit_operand(dst, src);
 }
 
@@ -504,8 +500,8 @@ void Assembler::movq(Register dst, Register src) {
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   emit_rex_64(dst, src);
-  EMIT(0x8B);
-  EMIT(0xC0 | (dst.code() & 0x7) << 3 | (src.code() & 0x7));
+  emit(0x8B);
+  emit(0xC0 | (dst.code() & 0x7) << 3 | (src.code() & 0x7));
 }
 
 
@@ -513,8 +509,8 @@ void Assembler::movq(Register dst, Immediate value) {
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   emit_rex_64(rax, dst);
-  EMIT(0xC7);
-  EMIT(0xC0 | (dst.code() & 0x7));
+  emit(0xC7);
+  emit(0xC0 | (dst.code() & 0x7));
   emit(value);  // Only 32-bit immediates are possible, not 8-bit immediates.
 }
 
@@ -523,7 +519,7 @@ void Assembler::movq(Register dst, int64_t value, RelocInfo::Mode rmode) {
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   emit_rex_64(rax, dst);
-  EMIT(0xB8 | (dst.code() & 0x7));
+  emit(0xB8 | (dst.code() & 0x7));
   emitq(value, rmode);
 }
 
@@ -531,7 +527,7 @@ void Assembler::movq(Register dst, int64_t value, RelocInfo::Mode rmode) {
 void Assembler::nop() {
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
-  EMIT(0x90);
+  emit(0x90);
 }
 
 
@@ -541,7 +537,7 @@ void Assembler::pop(Register dst) {
   if (dst.code() & 0x8) {
     emit_rex_64(rax, dst);
   }
-  EMIT(0x58 | (dst.code() & 0x7));
+  emit(0x58 | (dst.code() & 0x7));
 }
 
 
@@ -549,7 +545,7 @@ void Assembler::pop(const Operand& dst) {
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   emit_rex_64(rax, dst);  // Could be omitted in some cases.
-  EMIT(0x8F);
+  emit(0x8F);
   emit_operand(rax, dst);
 }
 
@@ -560,7 +556,7 @@ void Assembler::push(Register src) {
   if (src.code() & 0x8) {
     emit_rex_64(rax, src);
   }
-  EMIT(0x50 | (src.code() & 0x7));
+  emit(0x50 | (src.code() & 0x7));
 }
 
 
@@ -568,7 +564,7 @@ void Assembler::push(const Operand& src) {
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
   emit_rex_64(rsi, src);  // Could be omitted in some cases.
-  EMIT(0xFF);
+  emit(0xFF);
   emit_operand(rsi, src);
 }
 
@@ -578,11 +574,11 @@ void Assembler::ret(int imm16) {
   last_pc_ = pc_;
   ASSERT(is_uint16(imm16));
   if (imm16 == 0) {
-    EMIT(0xC3);
+    emit(0xC3);
   } else {
-    EMIT(0xC2);
-    EMIT(imm16 & 0xFF);
-    EMIT((imm16 >> 8) & 0xFF);
+    emit(0xC2);
+    emit(imm16 & 0xFF);
+    emit((imm16 >> 8) & 0xFF);
   }
 }
 
index e2f22bb80696487722bb355cdc3b161af7a88419..2a205b7ec10cb77f5d963897b4ceebc9bedb306e 100644 (file)
@@ -450,6 +450,7 @@ class Assembler : public Malloced {
     arithmetic_op(0x03, dst, src);
   }
 
+
   void add(const Operand& dst, Register src) {
     arithmetic_op(0x01, src, dst);
   }
@@ -482,11 +483,25 @@ class Assembler : public Malloced {
     immediate_arithmetic_op(0x7, dst, src);
   }
 
+  void and_(Register dst, Register src) {
+    arithmetic_op(0x23, dst, src);
+  }
+
+  void and_(Register dst, const Operand& src) {
+    arithmetic_op(0x23, dst, src);
+  }
+
+  void and_(const Operand& dst, Register src) {
+    arithmetic_op(0x21, src, dst);
+  }
+
+  void and_(Register dst, Immediate src) {
+    immediate_arithmetic_op(0x4, dst, src);
+  }
 
-  void and_(Register dst, int32_t imm32);
-  void and_(Register dst, const Operand& src);
-  void and_(const Operand& src, Register dst);
-  void and_(const Operand& dst, const Immediate& x);
+  void and_(const Operand& dst, Immediate src) {
+    immediate_arithmetic_op(0x4, dst, src);
+  }
 
   void cmpb(const Operand& op, int8_t imm8);
   void cmpb_al(const Operand& op);
@@ -516,10 +531,26 @@ class Assembler : public Malloced {
 
   void not_(Register dst);
 
-  void or_(Register dst, int32_t imm32);
-  void or_(Register dst, const Operand& src);
-  void or_(const Operand& dst, Register src);
-  void or_(const Operand& dst, const Immediate& x);
+  void or_(Register dst, Register src) {
+    arithmetic_op(0x0B, dst, src);
+  }
+
+  void or_(Register dst, const Operand& src) {
+    arithmetic_op(0x0B, dst, src);
+  }
+
+  void or_(const Operand& dst, Register src) {
+    arithmetic_op(0x09, src, dst);
+  }
+
+  void or_(Register dst, Immediate src) {
+    immediate_arithmetic_op(0x1, dst, src);
+  }
+
+  void or_(const Operand& dst, Immediate src) {
+    immediate_arithmetic_op(0x1, dst, src);
+  }
+
 
   void rcl(Register dst, uint8_t imm8);
 
@@ -539,18 +570,51 @@ class Assembler : public Malloced {
   void shr(Register dst);
   void shr_cl(Register dst);
 
-  void sub(const Operand& dst, const Immediate& x);
-  void sub(Register dst, const Operand& src);
-  void sub(const Operand& dst, Register src);
+  void sub(Register dst, Register src) {
+    arithmetic_op(0x2B, dst, src);
+  }
+
+  void sub(Register dst, const Operand& src) {
+    arithmetic_op(0x2B, dst, src);
+  }
+
+  void sub(const Operand& dst, Register src) {
+    arithmetic_op(0x29, src, dst);
+  }
+
+  void sub(Register dst, Immediate src) {
+    immediate_arithmetic_op(0x5, dst, src);
+  }
+
+  void sub(const Operand& dst, Immediate src) {
+    immediate_arithmetic_op(0x5, dst, src);
+  }
+
 
   void test(Register reg, const Immediate& imm);
   void test(Register reg, const Operand& op);
   void test(const Operand& op, const Immediate& imm);
 
-  void xor_(Register dst, int32_t imm32);
-  void xor_(Register dst, const Operand& src);
-  void xor_(const Operand& src, Register dst);
-  void xor_(const Operand& dst, const Immediate& x);
+  void xor_(Register dst, Register src) {
+    arithmetic_op(0x33, dst, src);
+  }
+
+  void xor_(Register dst, const Operand& src) {
+    arithmetic_op(0x33, dst, src);
+  }
+
+  void xor_(const Operand& dst, Register src) {
+    arithmetic_op(0x31, src, dst);
+  }
+
+  void xor_(Register dst, Immediate src) {
+    immediate_arithmetic_op(0x6, dst, src);
+  }
+
+  void xor_(const Operand& dst, Immediate src) {
+    immediate_arithmetic_op(0x6, dst, src);
+  }
+
 
   // Bit operations.
   void bt(const Operand& dst, Register src);
@@ -733,6 +797,8 @@ class Assembler : public Malloced {
 
   // code emission
   void GrowBuffer();
+
+  void emit(byte x) { *pc_++ = x; }
   inline void emitl(uint32_t x);
   inline void emit(Handle<Object> handle);
   inline void emitq(uint64_t x, RelocInfo::Mode rmode);
@@ -751,25 +817,23 @@ class Assembler : public Malloced {
   // is used for REX.X.  REX.W is set.
   inline void emit_rex_64(Register reg, 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, into the Mod/RM byte.
+  void emit_operand(Register reg, const Operand& adr);
+
   // Emit the code-object-relative offset of the label's position
   inline void emit_code_relative_offset(Label* label);
 
-  // instruction generation
-  void emit_arith_b(int op1, int op2, Register dst, int imm8);
-
-  // Emit a basic arithmetic instruction (i.e. first byte of the family is 0x81)
-  // with a given destination expression and an immediate operand.  It attempts
-  // to use the shortest encoding possible.
-  // sel specifies the /n in the modrm byte (see the Intel PRM).
+  // Emit machine code for one of the operations ADD, ADC, SUB, SBC,
+  // 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
+  // Mod/RM byte.
   void arithmetic_op(byte opcode, Register dst, Register src);
   void arithmetic_op(byte opcode, Register reg, const Operand& op);
   void immediate_arithmetic_op(byte subcode, Register dst, Immediate src);
   void immediate_arithmetic_op(byte subcode, const Operand& dst, Immediate src);
 
-  void emit_arith(int sel, Operand dst, const Immediate& x);
-
-  void emit_operand(Register reg, const Operand& adr);
-
   void emit_farith(int b1, int b2, int i);
 
   // labels