Revision: 15628
Author:   [email protected]
Date:     Thu Jul 11 06:07:04 2013
Log:      Implement X87 stack tracking and x87 multiplication

BUG=
[email protected]

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

Modified:
 /branches/bleeding_edge/src/ia32/assembler-ia32.cc
 /branches/bleeding_edge/src/ia32/assembler-ia32.h
 /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc
 /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.h
 /branches/bleeding_edge/src/ia32/lithium-gap-resolver-ia32.cc
 /branches/bleeding_edge/src/ia32/lithium-ia32.cc
 /branches/bleeding_edge/src/ia32/lithium-ia32.h

=======================================
--- /branches/bleeding_edge/src/ia32/assembler-ia32.cc Fri Jul 5 02:52:11 2013 +++ /branches/bleeding_edge/src/ia32/assembler-ia32.cc Thu Jul 11 06:07:04 2013
@@ -65,7 +65,7 @@
   if (CpuFeatures::IsSupported(SSE2)) {
     return XMMRegister::kNumAllocatableRegisters;
   } else {
-    return X87TopOfStackRegister::kNumAllocatableRegisters;
+    return X87Register::kNumAllocatableRegisters;
   }
 }

@@ -74,7 +74,7 @@
   if (CpuFeatures::IsSupported(SSE2)) {
     return XMMRegister::kNumRegisters;
   } else {
-    return X87TopOfStackRegister::kNumRegisters;
+    return X87Register::kNumRegisters;
   }
 }

@@ -83,7 +83,7 @@
   if (CpuFeatures::IsSupported(SSE2)) {
     return XMMRegister::AllocationIndexToString(index);
   } else {
-    return X87TopOfStackRegister::AllocationIndexToString(index);
+    return X87Register::AllocationIndexToString(index);
   }
 }

@@ -1782,6 +1782,12 @@
   EMIT(0xDA);
   emit_operand(esp, adr);
 }
+
+
+void Assembler::fmul_i(int i) {
+  EnsureSpace ensure_space(this);
+  emit_farith(0xD8, 0xC8, i);
+}


 void Assembler::fmul(int i) {
=======================================
--- /branches/bleeding_edge/src/ia32/assembler-ia32.h Wed Jun 12 09:23:17 2013 +++ /branches/bleeding_edge/src/ia32/assembler-ia32.h Thu Jul 11 06:07:04 2013
@@ -229,30 +229,40 @@
 #define xmm7 (static_cast<const XMMRegister&>(double_register_7))


-struct X87TopOfStackRegister : IntelDoubleRegister {
-  static const int kNumAllocatableRegisters = 1;
-  static const int kNumRegisters = 1;
+struct X87Register : IntelDoubleRegister {
+  static const int kNumAllocatableRegisters = 5;
+  static const int kNumRegisters = 5;

-  bool is(X87TopOfStackRegister reg) const {
+  bool is(X87Register reg) const {
     return code_ == reg.code_;
   }

   static const char* AllocationIndexToString(int index) {
     ASSERT(index >= 0 && index < kNumAllocatableRegisters);
     const char* const names[] = {
-      "st0",
+      "stX_0", "stX_1", "stX_2", "stX_3", "stX_4"
     };
     return names[index];
   }

-  static int ToAllocationIndex(X87TopOfStackRegister reg) {
-    ASSERT(reg.code() == 0);
-    return 0;
+  static X87Register FromAllocationIndex(int index) {
+    STATIC_ASSERT(sizeof(X87Register) == sizeof(IntelDoubleRegister));
+    ASSERT(index >= 0 && index < NumAllocatableRegisters());
+    X87Register result;
+    result.code_ = index;
+    return result;
+  }
+
+  static int ToAllocationIndex(X87Register reg) {
+    return reg.code_;
   }
 };

-#define x87tos \
-  static_cast<const X87TopOfStackRegister&>(double_register_0)
+#define stX_0 static_cast<const X87Register&>(double_register_0)
+#define stX_1 static_cast<const X87Register&>(double_register_1)
+#define stX_2 static_cast<const X87Register&>(double_register_2)
+#define stX_3 static_cast<const X87Register&>(double_register_3)
+#define stX_4 static_cast<const X87Register&>(double_register_4)


 typedef IntelDoubleRegister DoubleRegister;
@@ -947,6 +957,7 @@
   void fadd(int i);
   void fsub(int i);
   void fmul(int i);
+  void fmul_i(int i);
   void fdiv(int i);

   void fisub_s(const Operand& adr);
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Wed Jul 10 02:02:23 2013 +++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Thu Jul 11 06:07:04 2013
@@ -353,7 +353,6 @@
     instr->CompileToNative(this);

     if (!CpuFeatures::IsSupported(SSE2)) {
-      ASSERT(!instr->HasDoubleRegisterResult() || x87_stack_depth_ == 1);
       if (FLAG_debug_code && FLAG_enable_slow_asserts) {
         __ VerifyX87StackDepth(x87_stack_depth_);
       }
@@ -499,6 +498,11 @@
 Register LCodeGen::ToRegister(int index) const {
   return Register::FromAllocationIndex(index);
 }
+
+
+X87Register LCodeGen::ToX87Register(int index) const {
+  return X87Register::FromAllocationIndex(index);
+}


 XMMRegister LCodeGen::ToDoubleRegister(int index) const {
@@ -506,61 +510,169 @@
 }


-bool LCodeGen::IsX87TopOfStack(LOperand* op) const {
-  return op->IsDoubleRegister();
+void LCodeGen::X87LoadForUsage(X87Register reg) {
+  ASSERT(X87StackContains(reg));
+  X87Fxch(reg);
+  x87_stack_depth_--;
 }


-void LCodeGen::ReadX87Operand(Operand dst) {
-  ASSERT(x87_stack_depth_ == 1);
-  __ fst_d(dst);
+void LCodeGen::X87Fxch(X87Register reg, int other_slot) {
+  ASSERT(X87StackContains(reg) && x87_stack_depth_ > other_slot);
+  int i  = X87ArrayIndex(reg);
+  int st = x87_st2idx(i);
+  if (st != other_slot) {
+    int other_i = x87_st2idx(other_slot);
+    X87Register other   = x87_stack_[other_i];
+    x87_stack_[other_i] = reg;
+    x87_stack_[i]       = other;
+    if (st == 0) {
+      __ fxch(other_slot);
+    } else if (other_slot == 0) {
+      __ fxch(st);
+    } else {
+      __ fxch(st);
+      __ fxch(other_slot);
+      __ fxch(st);
+    }
+  }
 }


-void LCodeGen::PushX87DoubleOperand(Operand src) {
-  ASSERT(x87_stack_depth_ == 0);
-  x87_stack_depth_++;
-  __ fld_d(src);
+int LCodeGen::x87_st2idx(int pos) {
+  return x87_stack_depth_ - pos - 1;
+}
+
+
+int LCodeGen::X87ArrayIndex(X87Register reg) {
+  for (int i = 0; i < x87_stack_depth_; i++) {
+    if (x87_stack_[i].is(reg)) return i;
+  }
+  UNREACHABLE();
+  return -1;
 }


-void LCodeGen::PushX87FloatOperand(Operand src) {
-  ASSERT(x87_stack_depth_ == 0);
-  x87_stack_depth_++;
-  __ fld_s(src);
+bool LCodeGen::X87StackContains(X87Register reg) {
+  for (int i = 0; i < x87_stack_depth_; i++) {
+    if (x87_stack_[i].is(reg)) return true;
+  }
+  return false;
 }


-void LCodeGen::PopX87() {
-  ASSERT(x87_stack_depth_ == 1);
+void LCodeGen::X87Free(X87Register reg) {
+  ASSERT(X87StackContains(reg));
+  int i  = X87ArrayIndex(reg);
+  int st = x87_st2idx(i);
+  if (st > 0) {
+    // keep track of how fstp(i) changes the order of elements
+    int tos_i = x87_st2idx(0);
+    x87_stack_[i] = x87_stack_[tos_i];
+  }
   x87_stack_depth_--;
-  __ fstp(0);
+  __ fstp(st);
+}
+
+
+void LCodeGen::X87Mov(X87Register dst, Operand src, X87OperandType opts) {
+  if (X87StackContains(dst)) {
+    X87Fxch(dst);
+    __ fstp(0);
+  } else {
+    ASSERT(x87_stack_depth_ < X87Register::kNumAllocatableRegisters);
+    x87_stack_[x87_stack_depth_] = dst;
+    x87_stack_depth_++;
+  }
+  X87Fld(src, opts);
 }


-void LCodeGen::CurrentInstructionReturnsX87Result() {
-  ASSERT(x87_stack_depth_ <= 1);
-  if (x87_stack_depth_ == 0) {
-    x87_stack_depth_ = 1;
+void LCodeGen::X87Fld(Operand src, X87OperandType opts) {
+  if (opts == kX87DoubleOperand) {
+    __ fld_d(src);
+  } else if (opts == kX87FloatOperand) {
+    __ fld_s(src);
+  } else if (opts == kX87IntOperand) {
+    __ fild_s(src);
+  } else {
+    UNREACHABLE();
   }
 }
+
+
+void LCodeGen::X87Mov(Operand dst, X87Register src) {
+  X87Fxch(src);
+  __ fst_d(dst);
+}
+
+
+void LCodeGen::X87PrepareToWrite(X87Register reg) {
+  if (X87StackContains(reg)) {
+    X87Free(reg);
+  }
+  // Mark this register as the next register to write to
+  x87_stack_[x87_stack_depth_] = reg;
+}
+
+
+void LCodeGen::X87CommitWrite(X87Register reg) {
+  // Assert the reg is prepared to write, but not on the virtual stack yet
+  ASSERT(!X87StackContains(reg) && x87_stack_[x87_stack_depth_].is(reg) &&
+      x87_stack_depth_ < X87Register::kNumAllocatableRegisters);
+  x87_stack_depth_++;
+}
+
+
+void LCodeGen::X87PrepareBinaryOp(
+    X87Register left, X87Register right, X87Register result) {
+  // You need to use DefineSameAsFirst for x87 instructions
+  ASSERT(result.is(left));
+  X87Fxch(right, 1);
+  X87Fxch(left);
+}


 void LCodeGen::FlushX87StackIfNecessary(LInstruction* instr) {
-  if (x87_stack_depth_ > 0) {
-    if ((instr->ClobbersDoubleRegisters() ||
-         instr->HasDoubleRegisterResult()) &&
-        !instr->HasDoubleRegisterInput()) {
-      PopX87();
+  if (x87_stack_depth_ > 0 && instr->ClobbersDoubleRegisters()) {
+    bool double_inputs = instr->HasDoubleRegisterInput();
+
+    // Flush stack from tos down, since FreeX87() will mess with tos
+    for (int i = x87_stack_depth_-1; i >= 0; i--) {
+      X87Register reg = x87_stack_[i];
+      // Skip registers which contain the inputs for the next instruction
+      // when flushing the stack
+      if (double_inputs && instr->IsDoubleInput(reg, this)) {
+        continue;
+      }
+      X87Free(reg);
+      if (i < x87_stack_depth_-1) i++;
+    }
+  }
+  if (instr->IsReturn()) {
+    while (x87_stack_depth_ > 0) {
+      __ fstp(0);
+      x87_stack_depth_--;
     }
   }
 }
+
+
+void LCodeGen::EmitFlushX87ForDeopt() {
+  for (int i = 0; i < x87_stack_depth_; i++) __ fstp(0);
+}


 Register LCodeGen::ToRegister(LOperand* op) const {
   ASSERT(op->IsRegister());
   return ToRegister(op->index());
 }
+
+
+X87Register LCodeGen::ToX87Register(LOperand* op) const {
+  ASSERT(op->IsDoubleRegister());
+  return ToX87Register(op->index());
+}


 XMMRegister LCodeGen::ToDoubleRegister(LOperand* op) const {
@@ -835,8 +947,6 @@
                             Deoptimizer::BailoutType bailout_type) {
RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
   ASSERT(environment->HasBeenRegistered());
-  // It's an error to deoptimize with the x87 fp stack in use.
-  ASSERT(x87_stack_depth_ == 0);
   int id = environment->deoptimization_index();
   ASSERT(info()->IsOptimizing() || info()->IsStub());
   Address entry =
@@ -873,12 +983,21 @@
     __ pop(eax);
     __ popfd();
   }
+
+ // Before Instructions which can deopt, we normally flush the x87 stack. But
+  // we can have inputs or outputs of the current instruction on the stack,
+ // thus we need to flush them here from the physical stack to leave it in a
+  // consistent state.
+  if (x87_stack_depth_ > 0) {
+    Label done;
+    if (cc != no_condition) __ j(NegateCondition(cc), &done, Label::kNear);
+    EmitFlushX87ForDeopt();
+    __ bind(&done);
+  }

   if (FLAG_trap_on_deopt && info()->IsOptimizing()) {
     Label done;
-    if (cc != no_condition) {
-      __ j(NegateCondition(cc), &done, Label::kNear);
-    }
+    if (cc != no_condition) __ j(NegateCondition(cc), &done, Label::kNear);
     __ int3();
     __ bind(&done);
   }
@@ -1721,11 +1840,10 @@
   int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt));

   if (!CpuFeatures::IsSafeForSnapshot(SSE2)) {
+    __ push(Immediate(upper));
     __ push(Immediate(lower));
-    __ push(Immediate(upper));
-    PushX87DoubleOperand(Operand(esp, 0));
+    X87Mov(ToX87Register(instr->result()), Operand(esp, 0));
     __ add(Operand(esp), Immediate(kDoubleSize));
-    CurrentInstructionReturnsX87Result();
   } else {
     CpuFeatureScope scope1(masm(), SSE2);
     ASSERT(instr->result()->IsDoubleRegister());
@@ -1990,62 +2108,67 @@


 void LCodeGen::DoArithmeticD(LArithmeticD* instr) {
-  CpuFeatureScope scope(masm(), SSE2);
-  XMMRegister left = ToDoubleRegister(instr->left());
-  XMMRegister right = ToDoubleRegister(instr->right());
-  XMMRegister result = ToDoubleRegister(instr->result());
-  // Modulo uses a fixed result register.
-  ASSERT(instr->op() == Token::MOD || left.is(result));
-  switch (instr->op()) {
-    case Token::ADD:
-      __ addsd(left, right);
-      break;
-    case Token::SUB:
-      __ subsd(left, right);
-      break;
-    case Token::MUL:
-      __ mulsd(left, right);
-      break;
-    case Token::DIV:
-      __ divsd(left, right);
-      // Don't delete this mov. It may improve performance on some CPUs,
-      // when there is a mulsd depending on the result
-      __ movaps(left, left);
-      break;
-    case Token::MOD: {
-      // Pass two doubles as arguments on the stack.
-      __ PrepareCallCFunction(4, eax);
-      __ movdbl(Operand(esp, 0 * kDoubleSize), left);
-      __ movdbl(Operand(esp, 1 * kDoubleSize), right);
-      __ CallCFunction(
-          ExternalReference::double_fp_operation(Token::MOD, isolate()),
-          4);
+  if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
+    CpuFeatureScope scope(masm(), SSE2);
+    XMMRegister left = ToDoubleRegister(instr->left());
+    XMMRegister right = ToDoubleRegister(instr->right());
+    XMMRegister result = ToDoubleRegister(instr->result());
+    // Modulo uses a fixed result register.
+    ASSERT(instr->op() == Token::MOD || left.is(result));
+    switch (instr->op()) {
+      case Token::ADD:
+        __ addsd(left, right);
+        break;
+      case Token::SUB:
+        __ subsd(left, right);
+        break;
+      case Token::MUL:
+        __ mulsd(left, right);
+        break;
+      case Token::DIV:
+        __ divsd(left, right);
+        // Don't delete this mov. It may improve performance on some CPUs,
+        // when there is a mulsd depending on the result
+        __ movaps(left, left);
+        break;
+      case Token::MOD: {
+        // Pass two doubles as arguments on the stack.
+        __ PrepareCallCFunction(4, eax);
+        __ movdbl(Operand(esp, 0 * kDoubleSize), left);
+        __ movdbl(Operand(esp, 1 * kDoubleSize), right);
+        __ CallCFunction(
+            ExternalReference::double_fp_operation(Token::MOD, isolate()),
+            4);

-      // Return value is in st(0) on ia32.
-      // Store it into the (fixed) result register.
-      __ sub(Operand(esp), Immediate(kDoubleSize));
-      __ fstp_d(Operand(esp, 0));
-      __ movdbl(result, Operand(esp, 0));
-      __ add(Operand(esp), Immediate(kDoubleSize));
-      break;
+        // Return value is in st(0) on ia32.
+        // Store it into the (fixed) result register.
+        __ sub(Operand(esp), Immediate(kDoubleSize));
+        __ fstp_d(Operand(esp, 0));
+        __ movdbl(result, Operand(esp, 0));
+        __ add(Operand(esp), Immediate(kDoubleSize));
+        break;
+      }
+      default:
+        UNREACHABLE();
+        break;
     }
-    default:
-      UNREACHABLE();
-      break;
+  } else {
+    X87Register left = ToX87Register(instr->left());
+    X87Register right = ToX87Register(instr->right());
+    X87Register result = ToX87Register(instr->result());
+    X87PrepareBinaryOp(left, right, result);
+    switch (instr->op()) {
+      case Token::MUL:
+        __ fmul_i(1);
+        break;
+      default:
+        UNREACHABLE();
+        break;
+    }
   }
 }


-void LCodeGen::DoNegateNoSSE2D(LNegateNoSSE2D* instr) {
-  __ push(Immediate(-1));
-  __ fild_s(Operand(esp, 0));
-  __ add(esp, Immediate(kPointerSize));
-  __ fmulp();
-  CurrentInstructionReturnsX87Result();
-}
-
-
-
 void LCodeGen::DoArithmeticT(LArithmeticT* instr) {
   ASSERT(ToRegister(instr->context()).is(esi));
   ASSERT(ToRegister(instr->left()).is(edx));
@@ -2963,8 +3086,7 @@
       XMMRegister result = ToDoubleRegister(instr->result());
       __ movdbl(result, FieldOperand(object, offset));
     } else {
-      PushX87DoubleOperand(FieldOperand(object, offset));
-      CurrentInstructionReturnsX87Result();
+      X87Mov(ToX87Register(instr->result()), FieldOperand(object, offset));
     }
     return;
   }
@@ -3209,16 +3331,14 @@
       __ movss(result, operand);
       __ cvtss2sd(result, result);
     } else {
-      PushX87FloatOperand(operand);
-      CurrentInstructionReturnsX87Result();
+      X87Mov(ToX87Register(instr->result()), operand, kX87FloatOperand);
     }
   } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
     if (CpuFeatures::IsSupported(SSE2)) {
       CpuFeatureScope scope(masm(), SSE2);
       __ movdbl(ToDoubleRegister(instr->result()), operand);
     } else {
-      PushX87DoubleOperand(operand);
-      CurrentInstructionReturnsX87Result();
+      X87Mov(ToX87Register(instr->result()), operand);
     }
   } else {
     Register result(ToRegister(instr->result()));
@@ -3289,8 +3409,7 @@
     XMMRegister result = ToDoubleRegister(instr->result());
     __ movdbl(result, double_load_operand);
   } else {
-    PushX87DoubleOperand(double_load_operand);
-    CurrentInstructionReturnsX87Result();
+    X87Mov(ToX87Register(instr->result()), double_load_operand);
   }
 }

@@ -4284,7 +4403,8 @@
       XMMRegister value = ToDoubleRegister(instr->value());
       __ movdbl(FieldOperand(object, offset), value);
     } else {
-      __ fstp_d(FieldOperand(object, offset));
+      X87Register value = ToX87Register(instr->value());
+      X87Mov(FieldOperand(object, offset), value);
     }
     return;
   }
@@ -4410,7 +4530,7 @@
       CpuFeatureScope scope(masm(), SSE2);
       __ movdbl(operand, ToDoubleRegister(instr->value()));
     } else {
-      __ fst_d(operand);
+      X87Mov(operand, ToX87Register(instr->value()));
     }
   } else {
     Register value = ToRegister(instr->value());
@@ -4492,7 +4612,8 @@
       __ mov(double_store_operand2, Immediate(upper));
     } else {
       Label no_special_nan_handling;
-      ASSERT(x87_stack_depth_ > 0);
+      X87Register value = ToX87Register(instr->value());
+      X87Fxch(value);

       if (instr->NeedsCanonicalization()) {
         __ fld(0);
@@ -4961,17 +5082,22 @@
     HLoadKeyed* load = HLoadKeyed::cast(change_input);
     convert_hole = load->UsesMustHandleHole();
   }
+
+  bool use_sse2 = CpuFeatures::IsSupported(SSE2);
+  if (!use_sse2) {
+    // Put the value to the top of stack
+    X87Register src = ToX87Register(instr->value());
+    X87LoadForUsage(src);
+  }

   Label no_special_nan_handling;
   Label done;
   if (convert_hole) {
-    bool use_sse2 = CpuFeatures::IsSupported(SSE2);
     if (use_sse2) {
       CpuFeatureScope scope(masm(), SSE2);
       XMMRegister input_reg = ToDoubleRegister(instr->value());
       __ ucomisd(input_reg, input_reg);
     } else {
-      __ fld(0);
       __ fld(0);
       __ FCmp();
     }
@@ -5026,6 +5152,10 @@
   } else {
     __ fst_d(FieldOperand(reg, HeapNumber::kValueOffset));
   }
+  if (!use_sse2) {
+    // clean up the stack
+    __ fstp(0);
+  }
   __ bind(&done);
 }

@@ -5075,12 +5205,14 @@

 void LCodeGen::EmitNumberUntagDNoSSE2(Register input_reg,
                                       Register temp_reg,
+                                      X87Register res_reg,
                                       bool allow_undefined_as_nan,
                                       bool deoptimize_on_minus_zero,
                                       LEnvironment* env,
                                       NumberUntagDMode mode) {
   Label load_smi, done;

+  X87PrepareToWrite(res_reg);
   STATIC_ASSERT(NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE >
                 NUMBER_CANDIDATE_IS_ANY_TAGGED);
   if (mode >= NUMBER_CANDIDATE_IS_ANY_TAGGED) {
@@ -5141,6 +5273,7 @@
   __ pop(input_reg);
   __ SmiTag(input_reg);  // Retag smi.
   __ bind(&done);
+  X87CommitWrite(res_reg);
 }


@@ -5522,11 +5655,11 @@
   } else {
     EmitNumberUntagDNoSSE2(input_reg,
                            temp_reg,
+                           ToX87Register(instr->result()),
                            instr->hydrogen()->allow_undefined_as_nan(),
                            deoptimize_on_minus_zero,
                            instr->environment(),
                            mode);
-    CurrentInstructionReturnsX87Result();
   }
 }

=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.h Fri Jul 5 03:34:02 2013 +++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.h Thu Jul 11 06:07:04 2013
@@ -105,7 +105,7 @@
   Operand ToOperand(LOperand* op) const;
   Register ToRegister(LOperand* op) const;
   XMMRegister ToDoubleRegister(LOperand* op) const;
-  bool IsX87TopOfStack(LOperand* op) const;
+  X87Register ToX87Register(LOperand* op) const;

   bool IsInteger32(LConstantOperand* op) const;
   bool IsSmi(LConstantOperand* op) const;
@@ -118,14 +118,20 @@
   double ToDouble(LConstantOperand* op) const;

   // Support for non-sse2 (x87) floating point stack handling.
-  // These functions maintain the depth of the stack (either 0 or 1)
-  void PushX87DoubleOperand(Operand src);
-  void PushX87FloatOperand(Operand src);
-  void ReadX87Operand(Operand dst);
-  bool X87StackNonEmpty() const { return x87_stack_depth_ > 0; }
-  void PopX87();
-  void CurrentInstructionReturnsX87Result();
-  void FlushX87StackIfNecessary(LInstruction* instr);
+ // These functions maintain the mapping of physical stack registers to our
+  // virtual registers between instructions.
+ enum X87OperandType { kX87DoubleOperand, kX87FloatOperand, kX87IntOperand };
+
+  void X87Mov(X87Register reg, Operand src,
+      X87OperandType operand = kX87DoubleOperand);
+  void X87Mov(Operand src, X87Register reg);
+
+  void X87PrepareBinaryOp(
+      X87Register left, X87Register right, X87Register result);
+
+  void X87LoadForUsage(X87Register reg);
+  void X87PrepareToWrite(X87Register reg);
+  void X87CommitWrite(X87Register reg);

   Handle<Object> ToHandle(LConstantOperand* op) const;

@@ -292,6 +298,7 @@

   Register ToRegister(int index) const;
   XMMRegister ToDoubleRegister(int index) const;
+  X87Register ToX87Register(int index) const;
   int ToInteger32(LConstantOperand* op) const;

   Operand BuildFastArrayOperand(LOperand* elements_pointer,
@@ -331,6 +338,7 @@
   void EmitNumberUntagDNoSSE2(
       Register input,
       Register temp,
+      X87Register res_reg,
       bool allow_undefined_as_nan,
       bool deoptimize_on_minus_zero,
       LEnvironment* env,
@@ -392,6 +400,16 @@
   // register, or a stack slot operand.
   void EmitPushTaggedOperand(LOperand* operand);

+  void X87Fxch(X87Register reg, int other_slot = 0);
+  void X87Fld(Operand src, X87OperandType opts);
+  void X87Free(X87Register reg);
+
+  void FlushX87StackIfNecessary(LInstruction* instr);
+  void EmitFlushX87ForDeopt();
+  bool X87StackContains(X87Register reg);
+  int X87ArrayIndex(X87Register reg);
+  int x87_st2idx(int pos);
+
   Zone* zone_;
   LPlatformChunk* const chunk_;
   MacroAssembler* const masm_;
@@ -413,6 +431,7 @@
   int osr_pc_offset_;
   int last_lazy_deopt_pc_;
   bool frame_is_built_;
+  X87Register x87_stack_[X87Register::kNumAllocatableRegisters];
   int x87_stack_depth_;

   // Builder that keeps track of safepoints in the code. The table
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-gap-resolver-ia32.cc Fri Jul 5 03:34:02 2013 +++ /branches/bleeding_edge/src/ia32/lithium-gap-resolver-ia32.cc Thu Jul 11 06:07:04 2013
@@ -332,10 +332,8 @@
       } else {
         __ push(Immediate(upper));
         __ push(Immediate(lower));
-        if (cgen_->X87StackNonEmpty()) {
-          cgen_->PopX87();
-        }
-        cgen_->PushX87DoubleOperand(MemOperand(esp, 0));
+        X87Register dst = cgen_->ToX87Register(destination);
+        cgen_->X87Mov(dst, MemOperand(esp, 0));
         __ add(esp, Immediate(kDoubleSize));
       }
     } else {
@@ -367,10 +365,10 @@
     } else {
// load from the register onto the stack, store in destination, which must
       // be a double stack slot in the non-SSE2 case.
-      ASSERT(source->index() == 0);  // source is on top of the stack
       ASSERT(destination->IsDoubleStackSlot());
       Operand dst = cgen_->ToOperand(destination);
-      cgen_->ReadX87Operand(dst);
+      X87Register src = cgen_->ToX87Register(source);
+      cgen_->X87Mov(dst, src);
     }
   } else if (source->IsDoubleStackSlot()) {
     if (CpuFeatures::IsSupported(SSE2)) {
@@ -403,10 +401,8 @@
         __ mov(dst1, tmp);
       } else {
         Operand src = cgen_->ToOperand(source);
-        if (cgen_->X87StackNonEmpty()) {
-          cgen_->PopX87();
-        }
-        cgen_->PushX87DoubleOperand(src);
+        X87Register dst = cgen_->ToX87Register(destination);
+        cgen_->X87Mov(dst, src);
       }
     }
   } else {
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.cc Wed Jul 10 02:02:23 2013 +++ /branches/bleeding_edge/src/ia32/lithium-ia32.cc Thu Jul 11 06:07:04 2013
@@ -80,6 +80,17 @@
   }
   return false;
 }
+
+
+bool LInstruction::IsDoubleInput(X87Register reg, LCodeGen* cgen) {
+  for (int i = 0; i < InputCount(); i++) {
+    LOperand* op = InputAt(i);
+    if (op != NULL && op->IsDoubleRegister()) {
+      if (cgen->ToX87Register(op).is(reg)) return true;
+    }
+  }
+  return false;
+}


 void LInstruction::PrintTo(StringStream* stream) {
@@ -492,12 +503,6 @@
   return new(zone()) LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER,
                                   XMMRegister::ToAllocationIndex(reg));
 }
-
-
-LUnallocated* LChunkBuilder::ToUnallocated(X87TopOfStackRegister reg) {
-  return new(zone()) LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER,
-      X87TopOfStackRegister::ToAllocationIndex(reg));
-}


 LOperand* LChunkBuilder::UseFixed(HValue* value, Register fixed_register) {
@@ -508,11 +513,6 @@
 LOperand* LChunkBuilder::UseFixedDouble(HValue* value, XMMRegister reg) {
   return Use(value, ToUnallocated(reg));
 }
-
-
-LOperand* LChunkBuilder::UseX87TopOfStack(HValue* value) {
-  return Use(value, ToUnallocated(x87tos));
-}


 LOperand* LChunkBuilder::UseRegister(HValue* value) {
@@ -640,13 +640,6 @@
     XMMRegister reg) {
   return Define(instr, ToUnallocated(reg));
 }
-
-
-template<int I, int T>
-LInstruction* LChunkBuilder::DefineX87TOS(
-    LTemplateInstruction<1, I, T>* instr) {
-  return Define(instr, ToUnallocated(x87tos));
-}


 LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
@@ -1577,17 +1570,7 @@
     }
     return DefineSameAsFirst(mul);
   } else if (instr->representation().IsDouble()) {
-    if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
-      return DoArithmeticD(Token::MUL, instr);
-    }
-    ASSERT(instr->right()->IsConstant() &&
-           static_cast<HConstant*>(instr->right())->DoubleValue() == -1);
- // TODO(olivf) This is currently just a hack to support the UnaryOp Minus
-    // Stub. This will go away once we can use more than one X87 register,
-    // thus fully support binary instructions without SSE2.
-    LOperand* left = UseX87TopOfStack(instr->left());
-    LNegateNoSSE2D* result = new(zone()) LNegateNoSSE2D(left);
-    return DefineX87TOS(result);
+    return DoArithmeticD(Token::MUL, instr);
   } else {
     ASSERT(instr->representation().IsSmiOrTagged());
     return DoArithmeticT(Token::MUL, instr);
@@ -1937,11 +1920,7 @@
                        ? TempRegister()
                        : NULL;
       LNumberUntagD* res = new(zone()) LNumberUntagD(value, temp);
-      if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
-        return AssignEnvironment(DefineAsRegister(res));
-      } else {
-        return AssignEnvironment(DefineX87TOS(res));
-      }
+      return AssignEnvironment(DefineAsRegister(res));
     } else if (to.IsSmi()) {
       HValue* val = instr->value();
       LOperand* value = UseRegister(val);
@@ -1976,9 +1955,7 @@
   } else if (from.IsDouble()) {
     if (to.IsTagged()) {
       info()->MarkAsDeferredCalling();
-      LOperand* value = CpuFeatures::IsSupported(SSE2)
-          ? UseRegisterAtStart(instr->value())
-          : UseAtStart(instr->value());
+      LOperand* value = UseRegisterAtStart(instr->value());
       LOperand* temp = FLAG_inline_new ? TempRegister() : NULL;

       // Make sure that temp and result_temp are different registers.
@@ -2140,12 +2117,8 @@
   } else if (r.IsDouble()) {
     double value = instr->DoubleValue();
     bool value_is_zero = BitCast<uint64_t, double>(value) == 0;
-    if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
-      LOperand* temp = value_is_zero ? NULL : TempRegister();
-      return DefineAsRegister(new(zone()) LConstantD(temp));
-    } else {
-      return DefineX87TOS(new(zone()) LConstantD(NULL));
-    }
+    LOperand* temp = value_is_zero ? NULL : TempRegister();
+    return DefineAsRegister(new(zone()) LConstantD(temp));
   } else if (r.IsTagged()) {
     return DefineAsRegister(new(zone()) LConstantT);
   } else {
@@ -2337,11 +2310,7 @@
     if (instr->value()->representation().IsDouble()) {
       LOperand* object = UseRegisterAtStart(instr->elements());
       LOperand* val = NULL;
-      if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
-        val = UseRegisterAtStart(instr->value());
-      } else if (!instr->IsConstantHoleStore()) {
-        val = UseX87TopOfStack(instr->value());
-      }
+      val = UseRegisterAtStart(instr->value());
       LOperand* key = UseRegisterOrConstantAtStart(instr->key());
       return new(zone()) LStoreKeyed(object, key, val);
     } else {
@@ -2471,11 +2440,7 @@
     val = UseTempRegister(instr->value());
   } else if (FLAG_track_double_fields &&
              instr->field_representation().IsDouble()) {
-    if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
-      val = UseRegisterAtStart(instr->value());
-    } else {
-      val = UseX87TopOfStack(instr->value());
-    }
+    val = UseRegisterAtStart(instr->value());
   } else {
     val = UseRegister(instr->value());
   }
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.h     Wed Jul 10 02:02:23 2013
+++ /branches/bleeding_edge/src/ia32/lithium-ia32.h     Thu Jul 11 06:07:04 2013
@@ -141,7 +141,6 @@
   V(MathTan)                                    \
   V(ModI)                                       \
   V(MulI)                                       \
-  V(NegateNoSSE2D)                              \
   V(NumberTagD)                                 \
   V(NumberTagI)                                 \
   V(NumberTagU)                                 \
@@ -265,7 +264,11 @@
   bool ClobbersTemps() const { return is_call_; }
   bool ClobbersRegisters() const { return is_call_; }
   virtual bool ClobbersDoubleRegisters() const {
-    return is_call_ || !CpuFeatures::IsSupported(SSE2);
+    return is_call_ ||
+      (!CpuFeatures::IsSupported(SSE2) &&
+       // We only have rudimentary X87Stack tracking, thus in general
+       // cannot handle deoptimization nor phi-nodes.
+       (HasEnvironment() || IsControl()));
   }

   virtual bool HasResult() const = 0;
@@ -273,6 +276,7 @@

   bool HasDoubleRegisterResult();
   bool HasDoubleRegisterInput();
+  bool IsDoubleInput(X87Register reg, LCodeGen* cgen);

   LOperand* FirstInput() { return InputAt(0); }
   LOperand* Output() { return HasResult() ? result() : NULL; }
@@ -377,7 +381,6 @@
 class LInstructionGap: public LGap {
  public:
   explicit LInstructionGap(HBasicBlock* block) : LGap(block) { }
-  virtual bool ClobbersDoubleRegisters() const { return false; }

   virtual bool HasInterestingComment(LCodeGen* gen) const {
     return !IsRedundant();
@@ -658,18 +661,6 @@
   DECLARE_HYDROGEN_ACCESSOR(MathFloorOfDiv)
 };

-
-class LNegateNoSSE2D: public LTemplateInstruction<1, 1, 0> {
- public:
-  explicit LNegateNoSSE2D(LOperand* value) {
-    inputs_[0] = value;
-  }
-
-  LOperand* value() { return inputs_[0]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(NegateNoSSE2D, "negate-no-sse2-d")
-};
-

 class LMulI: public LTemplateInstruction<1, 2, 1> {
  public:
@@ -1221,10 +1212,6 @@
   explicit LConstantD(LOperand* temp) {
     temps_[0] = temp;
   }
-
-  virtual bool ClobbersDoubleRegisters() const {
-    return false;
-  }

   LOperand* temp() { return temps_[0]; }

@@ -2206,9 +2193,7 @@
   LOperand* value() { return inputs_[0]; }
   LOperand* temp() { return temps_[0]; }

-  virtual bool ClobbersDoubleRegisters() const {
-    return false;
-  }
+  virtual bool ClobbersDoubleRegisters() const { return false; }

   DECLARE_CONCRETE_INSTRUCTION(NumberUntagD, "double-untag")
   DECLARE_HYDROGEN_ACCESSOR(Change);
@@ -2852,14 +2837,13 @@
   // Methods for getting operands for Use / Define / Temp.
   LUnallocated* ToUnallocated(Register reg);
   LUnallocated* ToUnallocated(XMMRegister reg);
-  LUnallocated* ToUnallocated(X87TopOfStackRegister reg);
+  LUnallocated* ToUnallocated(X87Register reg);

   // Methods for setting up define-use relationships.
   MUST_USE_RESULT LOperand* Use(HValue* value, LUnallocated* operand);
MUST_USE_RESULT LOperand* UseFixed(HValue* value, Register fixed_register);
   MUST_USE_RESULT LOperand* UseFixedDouble(HValue* value,
                                            XMMRegister fixed_register);
-  MUST_USE_RESULT LOperand* UseX87TopOfStack(HValue* value);

   // A value that is guaranteed to be allocated to a register.
// Operand created by UseRegister is guaranteed to be live until the end of

--
--
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/groups/opt_out.


Reply via email to