Revision: 4930
Author: [email protected]
Date: Wed Jun 23 07:05:18 2010
Log: X64: Change some fpu operations to use XMM registers.

Review URL: http://codereview.chromium.org/2827022
http://code.google.com/p/v8/source/detail?r=4930

Modified:
 /branches/bleeding_edge/src/x64/assembler-x64.cc
 /branches/bleeding_edge/src/x64/assembler-x64.h
 /branches/bleeding_edge/src/x64/codegen-x64.cc
 /branches/bleeding_edge/src/x64/disasm-x64.cc
 /branches/bleeding_edge/src/x64/ic-x64.cc

=======================================
--- /branches/bleeding_edge/src/x64/assembler-x64.cc Wed Jun 23 04:48:30 2010 +++ /branches/bleeding_edge/src/x64/assembler-x64.cc Wed Jun 23 07:05:18 2010
@@ -2604,6 +2604,28 @@
   emit(0x10);  // load
   emit_sse_operand(dst, src);
 }
+
+
+void Assembler::movss(XMMRegister dst, const Operand& src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit(0xF3);  // single
+  emit_optional_rex_32(dst, src);
+  emit(0x0F);
+  emit(0x10);  // load
+  emit_sse_operand(dst, src);
+}
+
+
+void Assembler::movss(const Operand& src, XMMRegister dst) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit(0xF3);  // single
+  emit_optional_rex_32(dst, src);
+  emit(0x0F);
+  emit(0x11);  // store
+  emit_sse_operand(dst, src);
+}


 void Assembler::cvttss2si(Register dst, const Operand& src) {
@@ -2659,6 +2681,17 @@
   emit(0x2A);
   emit_sse_operand(dst, src);
 }
+
+
+void Assembler::cvtlsi2ss(XMMRegister dst, Register src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit(0xF3);
+  emit_optional_rex_32(dst, src);
+  emit(0x0F);
+  emit(0x2A);
+  emit_sse_operand(dst, src);
+}


 void Assembler::cvtqsi2sd(XMMRegister dst, Register src) {
@@ -2681,6 +2714,28 @@
   emit(0x5A);
   emit_sse_operand(dst, src);
 }
+
+
+void Assembler::cvtss2sd(XMMRegister dst, const Operand& src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit(0xF3);
+  emit_optional_rex_32(dst, src);
+  emit(0x0F);
+  emit(0x5A);
+  emit_sse_operand(dst, src);
+}
+
+
+void Assembler::cvtsd2ss(XMMRegister dst, XMMRegister src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit(0xF2);
+  emit_optional_rex_32(dst, src);
+  emit(0x0F);
+  emit(0x5A);
+  emit_sse_operand(dst, src);
+}


 void Assembler::addsd(XMMRegister dst, XMMRegister src) {
@@ -2760,6 +2815,18 @@
 }


+void Assembler::ucomisd(XMMRegister dst, const Operand& src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit(0x66);
+  emit_optional_rex_32(dst, src);
+  emit(0x0f);
+  emit(0x2e);
+  emit_sse_operand(dst, src);
+}
+
+
+
 void Assembler::emit_sse_operand(XMMRegister reg, const Operand& adr) {
   Register ireg = { reg.code() };
   emit_operand(ireg, adr);
=======================================
--- /branches/bleeding_edge/src/x64/assembler-x64.h     Wed Jun 23 04:48:30 2010
+++ /branches/bleeding_edge/src/x64/assembler-x64.h     Wed Jun 23 07:05:18 2010
@@ -1110,6 +1110,9 @@
   void movsd(XMMRegister dst, XMMRegister src);
   void movsd(XMMRegister dst, const Operand& src);

+  void movss(XMMRegister dst, const Operand& src);
+  void movss(const Operand& dst, XMMRegister src);
+
   void cvttss2si(Register dst, const Operand& src);
   void cvttsd2si(Register dst, const Operand& src);
   void cvttsd2siq(Register dst, XMMRegister src);
@@ -1119,7 +1122,11 @@
   void cvtqsi2sd(XMMRegister dst, const Operand& src);
   void cvtqsi2sd(XMMRegister dst, Register src);

+  void cvtlsi2ss(XMMRegister dst, Register src);
+
   void cvtss2sd(XMMRegister dst, XMMRegister src);
+  void cvtss2sd(XMMRegister dst, const Operand& src);
+  void cvtsd2ss(XMMRegister dst, XMMRegister src);

   void addsd(XMMRegister dst, XMMRegister src);
   void subsd(XMMRegister dst, XMMRegister src);
@@ -1130,6 +1137,7 @@
   void sqrtsd(XMMRegister dst, XMMRegister src);

   void ucomisd(XMMRegister dst, XMMRegister src);
+  void ucomisd(XMMRegister dst, const Operand& src);

// The first argument is the reg field, the second argument is the r/m field.
   void emit_sse_operand(XMMRegister dst, XMMRegister src);
=======================================
--- /branches/bleeding_edge/src/x64/codegen-x64.cc      Wed Jun 23 02:21:32 2010
+++ /branches/bleeding_edge/src/x64/codegen-x64.cc      Wed Jun 23 07:05:18 2010
@@ -5336,9 +5336,8 @@
     dest->false_target()->Branch(equal);
     Condition is_smi = masm_->CheckSmi(value.reg());
     dest->true_target()->Branch(is_smi);
-    __ fldz();
-    __ fld_d(FieldOperand(value.reg(), HeapNumber::kValueOffset));
-    __ FCmp();
+    __ xorpd(xmm0, xmm0);
+    __ ucomisd(xmm0, FieldOperand(value.reg(), HeapNumber::kValueOffset));
     value.Unuse();
     dest->Split(not_zero);
   } else {
@@ -8000,14 +7999,12 @@
   __ jmp(&true_result);

   __ bind(&not_string);
-  // HeapNumber => false iff +0, -0, or NaN.
-  // These three cases set C3 when compared to zero in the FPU.
   __ CompareRoot(rdx, Heap::kHeapNumberMapRootIndex);
   __ j(not_equal, &true_result);
-  __ fldz();  // Load zero onto fp stack
-  // Load heap-number double value onto fp stack
-  __ fld_d(FieldOperand(rax, HeapNumber::kValueOffset));
-  __ FCmp();
+  // HeapNumber => false iff +0, -0, or NaN.
+ // These three cases set the zero flag when compared to zero using ucomisd.
+  __ xorpd(xmm0, xmm0);
+  __ ucomisd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset));
   __ j(zero, &false_result);
   // Fall through to |true_result|.

=======================================
--- /branches/bleeding_edge/src/x64/disasm-x64.cc       Wed Jun 23 04:48:30 2010
+++ /branches/bleeding_edge/src/x64/disasm-x64.cc       Wed Jun 23 07:05:18 2010
@@ -1057,7 +1057,7 @@
       // CVTSI2SD: integer to XMM double conversion.
       int mod, regop, rm;
       get_modrm(*current, &mod, &regop, &rm);
-      AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
+      AppendToBuffer("%sd %s,", mnemonic, NameOfXMMRegister(regop));
       current += PrintRightOperand(current);
     } else if ((opcode & 0xF8) == 0x58 || opcode == 0x51) {
// XMM arithmetic. Mnemonic was retrieved at the start of this function.
@@ -1070,7 +1070,25 @@
     }
   } else if (group_1_prefix_ == 0xF3) {
     // Instructions with prefix 0xF3.
-    if (opcode == 0x2C) {
+    if (opcode == 0x11 || opcode == 0x10) {
+ // MOVSS: Move scalar double-precision fp to/from/between XMM registers.
+      AppendToBuffer("movss ");
+      int mod, regop, rm;
+      get_modrm(*current, &mod, &regop, &rm);
+      if (opcode == 0x11) {
+        current += PrintRightOperand(current);
+        AppendToBuffer(",%s", NameOfXMMRegister(regop));
+      } else {
+        AppendToBuffer("%s,", NameOfXMMRegister(regop));
+        current += PrintRightOperand(current);
+      }
+    } else if (opcode == 0x2A) {
+      // CVTSI2SS: integer to XMM single conversion.
+      int mod, regop, rm;
+      get_modrm(*current, &mod, &regop, &rm);
+      AppendToBuffer("%ss %s,", mnemonic, NameOfXMMRegister(regop));
+      current += PrintRightOperand(current);
+    } else if (opcode == 0x2C) {
       // CVTTSS2SI: Convert scalar single-precision FP to dword integer.
// Assert that mod is not 3, so source is memory, not an XMM register.
       ASSERT_NE(0xC0, *current & 0xC0);
@@ -1146,8 +1164,8 @@
   switch (opcode) {
     case 0x1F:
       return "nop";
-    case 0x2A:  // F2 prefix.
-      return "cvtsi2sd";
+    case 0x2A:  // F2/F3 prefix.
+      return "cvtsi2s";
     case 0x31:
       return "rdtsc";
     case 0x51:  // F2 prefix.
=======================================
--- /branches/bleeding_edge/src/x64/ic-x64.cc   Wed Jun 23 02:10:21 2010
+++ /branches/bleeding_edge/src/x64/ic-x64.cc   Wed Jun 23 07:05:18 2010
@@ -702,7 +702,7 @@
   //  -- rdx    : receiver
   //  -- rsp[0] : return address
   // -----------------------------------
-  Label slow, failed_allocation;
+  Label slow;

   // Check that the object isn't a smi.
   __ JumpIfSmi(rdx, &slow);
@@ -761,7 +761,7 @@
       __ movl(rcx, Operand(rbx, rcx, times_4, 0));
       break;
     case kExternalFloatArray:
-      __ fld_s(Operand(rbx, rcx, times_4, 0));
+      __ cvtss2sd(xmm0, Operand(rbx, rcx, times_4, 0));
       break;
     default:
       UNREACHABLE();
@@ -773,20 +773,16 @@
   // For integer array types:
   // rcx: value
   // For floating-point array type:
-  // FP(0): value
-
-  if (array_type == kExternalIntArray ||
-      array_type == kExternalUnsignedIntArray) {
-    // For the Int and UnsignedInt array types, we need to see whether
+  // xmm0: value as double.
+
+  ASSERT(kSmiValueSize == 32);
+  if (array_type == kExternalUnsignedIntArray) {
+    // For the UnsignedInt array type, we need to see whether
     // the value can be represented in a Smi. If not, we need to convert
     // it to a HeapNumber.
     Label box_int;
-    if (array_type == kExternalIntArray) {
-      __ JumpIfNotValidSmiValue(rcx, &box_int);
-    } else {
-      ASSERT_EQ(array_type, kExternalUnsignedIntArray);
-      __ JumpIfUIntNotValidSmiValue(rcx, &box_int);
-    }
+
+    __ JumpIfUIntNotValidSmiValue(rcx, &box_int);

     __ Integer32ToSmi(rax, rcx);
     __ ret(0);
@@ -795,41 +791,28 @@

     // Allocate a HeapNumber for the int and perform int-to-double
     // conversion.
-    __ push(rcx);
-    if (array_type == kExternalIntArray) {
-      __ fild_s(Operand(rsp, 0));
-    } else {
-      ASSERT(array_type == kExternalUnsignedIntArray);
-      // The value is zero-extended on the stack, because all pushes are
-      // 64-bit and we loaded the value from memory with movl.
-      __ fild_d(Operand(rsp, 0));
-    }
-    __ pop(rcx);
-    // FP(0): value
-    __ AllocateHeapNumber(rcx, rbx, &failed_allocation);
+    ASSERT(array_type == kExternalUnsignedIntArray);
+    // The value is zero-extended since we loaded the value from memory
+    // with movl.
+    __ cvtqsi2sd(xmm0, rcx);
+
+    __ AllocateHeapNumber(rcx, rbx, &slow);
     // Set the value.
+    __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0);
     __ movq(rax, rcx);
-    __ fstp_d(FieldOperand(rax, HeapNumber::kValueOffset));
     __ ret(0);
   } else if (array_type == kExternalFloatArray) {
     // For the floating-point array type, we need to always allocate a
     // HeapNumber.
-    __ AllocateHeapNumber(rcx, rbx, &failed_allocation);
+    __ AllocateHeapNumber(rcx, rbx, &slow);
     // Set the value.
+    __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0);
     __ movq(rax, rcx);
-    __ fstp_d(FieldOperand(rax, HeapNumber::kValueOffset));
     __ ret(0);
   } else {
     __ Integer32ToSmi(rax, rcx);
     __ ret(0);
   }
-
-  // If we fail allocation of the HeapNumber, we still have a value on
-  // top of the FPU stack. Remove it.
-  __ bind(&failed_allocation);
-  __ ffree();
-  __ fincstp();
-  // Fall through to slow case.

   // Slow case: Jump to runtime.
   __ bind(&slow);
@@ -1116,10 +1099,8 @@
       break;
     case kExternalFloatArray:
       // Need to perform int-to-float conversion.
-      __ push(rdx);
-      __ fild_s(Operand(rsp, 0));
-      __ pop(rdx);
-      __ fstp_s(Operand(rbx, rdi, times_4, 0));
+      __ cvtlsi2ss(xmm0, rdx);
+      __ movss(Operand(rbx, rdi, times_4, 0), xmm0);
       break;
     default:
       UNREACHABLE();
@@ -1156,6 +1137,8 @@
     __ j(parity_even, &is_nan);

__ push(rdx); // Make room on the stack. Receiver is no longer needed. + // TODO(lrn): If the rounding of this conversion is not deliberate, maybe
+    // switch to xmm registers.
     __ fistp_d(Operand(rsp, 0));
     __ pop(rdx);
     // rdx: value (converted to an untagged integer)
@@ -1201,7 +1184,7 @@
     // rbx: base pointer of external storage
     __ ffree();
     __ fincstp();
-    __ movq(rdx, Immediate(0));
+    __ Set(rdx, 0);
     switch (array_type) {
       case kExternalByteArray:
       case kExternalUnsignedByteArray:

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

Reply via email to