[turbofan] support all shift operands on x64
authordcarney@chromium.org <dcarney@chromium.org>
Thu, 2 Oct 2014 09:08:09 +0000 (09:08 +0000)
committerdcarney@chromium.org <dcarney@chromium.org>
Thu, 2 Oct 2014 09:08:09 +0000 (09:08 +0000)
R=bmeurer@chromium.org

BUG=

Review URL: https://codereview.chromium.org/615223005

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

src/compiler/x64/code-generator-x64.cc
src/compiler/x64/instruction-selector-x64.cc
src/x64/assembler-x64.cc
src/x64/assembler-x64.h
src/x64/disasm-x64.cc
test/cctest/test-disasm-x64.cc

index 37aca10..6f9d68f 100644 (file)
@@ -184,13 +184,21 @@ static bool HasImmediateInput(Instruction* instr, int index) {
   } while (0)
 
 
-#define ASSEMBLE_SHIFT(asm_instr, width)                                 \
-  do {                                                                   \
-    if (HasImmediateInput(instr, 1)) {                                   \
-      __ asm_instr(i.OutputRegister(), Immediate(i.InputInt##width(1))); \
-    } else {                                                             \
-      __ asm_instr##_cl(i.OutputRegister());                             \
-    }                                                                    \
+#define ASSEMBLE_SHIFT(asm_instr, width)                                   \
+  do {                                                                     \
+    if (HasImmediateInput(instr, 1)) {                                     \
+      if (instr->Output()->IsRegister()) {                                 \
+        __ asm_instr(i.OutputRegister(), Immediate(i.InputInt##width(1))); \
+      } else {                                                             \
+        __ asm_instr(i.OutputOperand(), Immediate(i.InputInt##width(1)));  \
+      }                                                                    \
+    } else {                                                               \
+      if (instr->Output()->IsRegister()) {                                 \
+        __ asm_instr##_cl(i.OutputRegister());                             \
+      } else {                                                             \
+        __ asm_instr##_cl(i.OutputOperand());                              \
+      }                                                                    \
+    }                                                                      \
   } while (0)
 
 
index 8f52606..f744a2c 100644 (file)
@@ -21,8 +21,6 @@ class X64OperandGenerator FINAL : public OperandGenerator {
                                            Register::ToAllocationIndex(reg));
   }
 
-  InstructionOperand* UseImmediate64(Node* node) { return UseImmediate(node); }
-
   bool CanBeImmediate(Node* node) {
     switch (node->opcode()) {
       case IrOpcode::kInt32Constant:
@@ -32,23 +30,6 @@ class X64OperandGenerator FINAL : public OperandGenerator {
     }
   }
 
-  bool CanBeImmediate64(Node* node) {
-    switch (node->opcode()) {
-      case IrOpcode::kInt32Constant:
-        return true;
-      case IrOpcode::kNumberConstant:
-        return true;
-      case IrOpcode::kHeapConstant: {
-        // Constants in new space cannot be used as immediates in V8 because
-        // the GC does not scan code objects when collecting the new generation.
-        Unique<HeapObject> value = OpParameter<Unique<HeapObject> >(node);
-        return !isolate()->heap()->InNewSpace(*value.handle());
-      }
-      default:
-        return false;
-    }
-  }
-
   bool CanBeBetterLeftOperand(Node* node) const {
     return !selector()->IsLive(node);
   }
@@ -350,9 +331,8 @@ static void VisitWord32Shift(InstructionSelector* selector, Node* node,
   Node* left = node->InputAt(0);
   Node* right = node->InputAt(1);
 
-  // TODO(turbofan): assembler only supports some addressing modes for shifts.
   if (g.CanBeImmediate(right)) {
-    selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left),
+    selector->Emit(opcode, g.DefineSameAsFirst(node), g.Use(left),
                    g.UseImmediate(right));
   } else {
     Int32BinopMatcher m(node);
@@ -362,7 +342,7 @@ static void VisitWord32Shift(InstructionSelector* selector, Node* node,
         right = mright.left().node();
       }
     }
-    selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left),
+    selector->Emit(opcode, g.DefineSameAsFirst(node), g.Use(left),
                    g.UseFixed(right, rcx));
   }
 }
@@ -376,9 +356,8 @@ static void VisitWord64Shift(InstructionSelector* selector, Node* node,
   Node* left = node->InputAt(0);
   Node* right = node->InputAt(1);
 
-  // TODO(turbofan): assembler only supports some addressing modes for shifts.
   if (g.CanBeImmediate(right)) {
-    selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left),
+    selector->Emit(opcode, g.DefineSameAsFirst(node), g.Use(left),
                    g.UseImmediate(right));
   } else {
     Int64BinopMatcher m(node);
@@ -388,7 +367,7 @@ static void VisitWord64Shift(InstructionSelector* selector, Node* node,
         right = mright.left().node();
       }
     }
-    selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left),
+    selector->Emit(opcode, g.DefineSameAsFirst(node), g.Use(left),
                    g.UseFixed(right, rcx));
   }
 }
index a9fb834..8cc5395 100644 (file)
@@ -617,6 +617,24 @@ void Assembler::shift(Register dst,
 }
 
 
+void Assembler::shift(Operand dst, Immediate shift_amount, int subcode,
+                      int size) {
+  EnsureSpace ensure_space(this);
+  DCHECK(size == kInt64Size ? is_uint6(shift_amount.value_)
+                            : is_uint5(shift_amount.value_));
+  if (shift_amount.value_ == 1) {
+    emit_rex(dst, size);
+    emit(0xD1);
+    emit_operand(subcode, dst);
+  } else {
+    emit_rex(dst, size);
+    emit(0xC1);
+    emit_operand(subcode, dst);
+    emit(shift_amount.value_);
+  }
+}
+
+
 void Assembler::shift(Register dst, int subcode, int size) {
   EnsureSpace ensure_space(this);
   emit_rex(dst, size);
@@ -625,6 +643,14 @@ void Assembler::shift(Register dst, int subcode, int size) {
 }
 
 
+void Assembler::shift(Operand dst, int subcode, int size) {
+  EnsureSpace ensure_space(this);
+  emit_rex(dst, size);
+  emit(0xD3);
+  emit_operand(subcode, dst);
+}
+
+
 void Assembler::bt(const Operand& dst, Register src) {
   EnsureSpace ensure_space(this);
   emit_rex_64(src, dst);
index 529b100..b461124 100644 (file)
@@ -813,30 +813,42 @@ class Assembler : public AssemblerBase {
   // Multiply rax by src, put the result in rdx:rax.
   void mul(Register src);
 
-#define DECLARE_SHIFT_INSTRUCTION(instruction, subcode)     \
-  void instruction##p(Register dst, Immediate imm8) {       \
-    shift(dst, imm8, subcode, kPointerSize);                \
-  }                                                         \
-                                                            \
-  void instruction##l(Register dst, Immediate imm8) {       \
-    shift(dst, imm8, subcode, kInt32Size);                  \
-  }                                                         \
-                                                            \
-  void instruction##q(Register dst, Immediate imm8) {       \
-    shift(dst, imm8, subcode, kInt64Size);                  \
-  }                                                         \
-                                                            \
-  void instruction##p_cl(Register dst) {                    \
-    shift(dst, subcode, kPointerSize);                      \
-  }                                                         \
-                                                            \
-  void instruction##l_cl(Register dst) {                    \
-    shift(dst, subcode, kInt32Size);                        \
-  }                                                         \
-                                                            \
-  void instruction##q_cl(Register dst) {                    \
-    shift(dst, subcode, kInt64Size);                        \
-  }
+#define DECLARE_SHIFT_INSTRUCTION(instruction, subcode)                       \
+  void instruction##p(Register dst, Immediate imm8) {                         \
+    shift(dst, imm8, subcode, kPointerSize);                                  \
+  }                                                                           \
+                                                                              \
+  void instruction##l(Register dst, Immediate imm8) {                         \
+    shift(dst, imm8, subcode, kInt32Size);                                    \
+  }                                                                           \
+                                                                              \
+  void instruction##q(Register dst, Immediate imm8) {                         \
+    shift(dst, imm8, subcode, kInt64Size);                                    \
+  }                                                                           \
+                                                                              \
+  void instruction##p(Operand dst, Immediate imm8) {                          \
+    shift(dst, imm8, subcode, kPointerSize);                                  \
+  }                                                                           \
+                                                                              \
+  void instruction##l(Operand dst, Immediate imm8) {                          \
+    shift(dst, imm8, subcode, kInt32Size);                                    \
+  }                                                                           \
+                                                                              \
+  void instruction##q(Operand dst, Immediate imm8) {                          \
+    shift(dst, imm8, subcode, kInt64Size);                                    \
+  }                                                                           \
+                                                                              \
+  void instruction##p_cl(Register dst) { shift(dst, subcode, kPointerSize); } \
+                                                                              \
+  void instruction##l_cl(Register dst) { shift(dst, subcode, kInt32Size); }   \
+                                                                              \
+  void instruction##q_cl(Register dst) { shift(dst, subcode, kInt64Size); }   \
+                                                                              \
+  void instruction##p_cl(Operand dst) { shift(dst, subcode, kPointerSize); }  \
+                                                                              \
+  void instruction##l_cl(Operand dst) { shift(dst, subcode, kInt32Size); }    \
+                                                                              \
+  void instruction##q_cl(Operand dst) { shift(dst, subcode, kInt64Size); }
   SHIFT_INSTRUCTION_LIST(DECLARE_SHIFT_INSTRUCTION)
 #undef DECLARE_SHIFT_INSTRUCTION
 
@@ -1365,9 +1377,11 @@ class Assembler : public AssemblerBase {
                                int size);
 
   // Emit machine code for a shift operation.
+  void shift(Operand dst, Immediate shift_amount, int subcode, int size);
   void shift(Register dst, Immediate shift_amount, int subcode, int size);
   // Shift dst by cl % 64 bits.
   void shift(Register dst, int subcode, int size);
+  void shift(Operand dst, int subcode, int size);
 
   void emit_farith(int b1, int b2, int i);
 
index 2b8fc2d..9b55883 100644 (file)
@@ -709,65 +709,62 @@ int DisassemblerX64::F6F7Instruction(byte* data) {
 
 int DisassemblerX64::ShiftInstruction(byte* data) {
   byte op = *data & (~1);
+  int count = 1;
   if (op != 0xD0 && op != 0xD2 && op != 0xC0) {
     UnimplementedInstruction();
-    return 1;
+    return count;
   }
-  byte modrm = *(data + 1);
-  int mod, regop, rm;
-  get_modrm(modrm, &mod, &regop, &rm);
-  regop &= 0x7;  // The REX.R bit does not affect the operation.
-  int imm8 = -1;
-  int num_bytes = 2;
-  if (mod != 3) {
-    UnimplementedInstruction();
-    return num_bytes;
-  }
-  const char* mnem = NULL;
-  switch (regop) {
-    case 0:
-      mnem = "rol";
-      break;
-    case 1:
-      mnem = "ror";
-      break;
-    case 2:
-      mnem = "rcl";
-      break;
-    case 3:
-      mnem = "rcr";
-      break;
-    case 4:
-      mnem = "shl";
-      break;
-    case 5:
-      mnem = "shr";
-      break;
-    case 7:
-      mnem = "sar";
-      break;
-    default:
-      UnimplementedInstruction();
-      return num_bytes;
-  }
-  DCHECK_NE(NULL, mnem);
-  if (op == 0xD0) {
-    imm8 = 1;
-  } else if (op == 0xC0) {
-    imm8 = *(data + 2);
-    num_bytes = 3;
+  // Print mneumonic.
+  {
+    byte modrm = *(data + count);
+    int mod, regop, rm;
+    get_modrm(modrm, &mod, &regop, &rm);
+    regop &= 0x7;  // The REX.R bit does not affect the operation.
+    const char* mnem = NULL;
+    switch (regop) {
+      case 0:
+        mnem = "rol";
+        break;
+      case 1:
+        mnem = "ror";
+        break;
+      case 2:
+        mnem = "rcl";
+        break;
+      case 3:
+        mnem = "rcr";
+        break;
+      case 4:
+        mnem = "shl";
+        break;
+      case 5:
+        mnem = "shr";
+        break;
+      case 7:
+        mnem = "sar";
+        break;
+      default:
+        UnimplementedInstruction();
+        return count + 1;
+    }
+    DCHECK_NE(NULL, mnem);
+    AppendToBuffer("%s%c ", mnem, operand_size_code());
   }
-  AppendToBuffer("%s%c %s,",
-                 mnem,
-                 operand_size_code(),
-                 byte_size_operand_ ? NameOfByteCPURegister(rm)
-                                    : NameOfCPURegister(rm));
+  count += PrintRightOperand(data + count);
   if (op == 0xD2) {
-    AppendToBuffer("cl");
+    AppendToBuffer("cl");
   } else {
-    AppendToBuffer("%d", imm8);
+    int imm8 = -1;
+    if (op == 0xD0) {
+      imm8 = 1;
+    } else {
+      DCHECK_EQ(0xC0, op);
+      imm8 = *(data + count);
+      count++;
+    }
+    AppendToBuffer(", %d", imm8);
   }
-  return num_bytes;
+  return count;
 }
 
 
index 480c91f..3fd3ef1 100644 (file)
@@ -117,6 +117,26 @@ TEST(DisasmX64) {
   __ imulq(rdx, rcx);
   __ shld(rdx, rcx);
   __ shrd(rdx, rcx);
+  __ shlq(Operand(rdi, rax, times_4, 100), Immediate(1));
+  __ shlq(Operand(rdi, rax, times_4, 100), Immediate(6));
+  __ shlq(Operand(r15, 0), Immediate(1));
+  __ shlq(Operand(r15, 0), Immediate(6));
+  __ shlq_cl(Operand(r15, 0));
+  __ shlq_cl(Operand(r15, 0));
+  __ shlq_cl(Operand(rdi, rax, times_4, 100));
+  __ shlq_cl(Operand(rdi, rax, times_4, 100));
+  __ shlq(rdx, Immediate(1));
+  __ shlq(rdx, Immediate(6));
+  __ shll(Operand(rdi, rax, times_4, 100), Immediate(1));
+  __ shll(Operand(rdi, rax, times_4, 100), Immediate(6));
+  __ shll(Operand(r15, 0), Immediate(1));
+  __ shll(Operand(r15, 0), Immediate(6));
+  __ shll_cl(Operand(r15, 0));
+  __ shll_cl(Operand(r15, 0));
+  __ shll_cl(Operand(rdi, rax, times_4, 100));
+  __ shll_cl(Operand(rdi, rax, times_4, 100));
+  __ shll(rdx, Immediate(1));
+  __ shll(rdx, Immediate(6));
   __ bts(Operand(rdx, 0), rcx);
   __ bts(Operand(rbx, rcx, times_4, 0), rcx);
   __ nop();