Revision: 16329
Author:   [email protected]
Date:     Mon Aug 26 14:51:51 2013 UTC
Log:      Port CompileMathFloorCall from ia32 to x64

BUG=
[email protected]

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

Patch from Weiliang Lin <[email protected]>.
http://code.google.com/p/v8/source/detail?r=16329

Modified:
 /branches/bleeding_edge/src/x64/assembler-x64.cc
 /branches/bleeding_edge/src/x64/assembler-x64.h
 /branches/bleeding_edge/src/x64/disasm-x64.cc
 /branches/bleeding_edge/src/x64/stub-cache-x64.cc

=======================================
--- /branches/bleeding_edge/src/x64/assembler-x64.cc Mon Aug 26 09:37:39 2013 UTC +++ /branches/bleeding_edge/src/x64/assembler-x64.cc Mon Aug 26 14:51:51 2013 UTC
@@ -2916,6 +2916,17 @@
   emit(0x2e);
   emit_sse_operand(dst, src);
 }
+
+
+void Assembler::cmpltsd(XMMRegister dst, XMMRegister src) {
+  EnsureSpace ensure_space(this);
+  emit(0xF2);
+  emit_optional_rex_32(dst, src);
+  emit(0x0F);
+  emit(0xC2);
+  emit_sse_operand(dst, src);
+  emit(0x01);  // LT == 1
+}


 void Assembler::roundsd(XMMRegister dst, XMMRegister src,
=======================================
--- /branches/bleeding_edge/src/x64/assembler-x64.h Thu Aug 22 11:58:20 2013 UTC +++ /branches/bleeding_edge/src/x64/assembler-x64.h Mon Aug 26 14:51:51 2013 UTC
@@ -1384,6 +1384,8 @@
   void movmskpd(Register dst, XMMRegister src);
   void movmskps(Register dst, XMMRegister src);

+  void cmpltsd(XMMRegister dst, XMMRegister src);
+
// The first argument is the reg field, the second argument is the r/m field.
   void emit_sse_operand(XMMRegister dst, XMMRegister src);
   void emit_sse_operand(XMMRegister reg, const Operand& adr);
=======================================
--- /branches/bleeding_edge/src/x64/disasm-x64.cc Thu Aug 22 11:58:20 2013 UTC +++ /branches/bleeding_edge/src/x64/disasm-x64.cc Mon Aug 26 14:51:51 2013 UTC
@@ -1153,6 +1153,25 @@
       get_modrm(*current, &mod, &regop, &rm);
       AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
       current += PrintRightXMMOperand(current);
+    } else if (opcode == 0xC2) {
+      // Intel manual 2A, Table 3-18.
+      int mod, regop, rm;
+      get_modrm(*current, &mod, &regop, &rm);
+      const char* const pseudo_op[] = {
+        "cmpeqsd",
+        "cmpltsd",
+        "cmplesd",
+        "cmpunordsd",
+        "cmpneqsd",
+        "cmpnltsd",
+        "cmpnlesd",
+        "cmpordsd"
+      };
+      AppendToBuffer("%s %s,%s",
+                     pseudo_op[current[1]],
+                     NameOfXMMRegister(regop),
+                     NameOfXMMRegister(rm));
+      current += 2;
     } else {
       UnimplementedInstruction();
     }
=======================================
--- /branches/bleeding_edge/src/x64/stub-cache-x64.cc Mon Aug 19 22:12:46 2013 UTC +++ /branches/bleeding_edge/src/x64/stub-cache-x64.cc Mon Aug 26 14:51:51 2013 UTC
@@ -2200,8 +2200,130 @@
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // TODO(872): implement this.
-  return Handle<Code>::null();
+  // ----------- S t a t e -------------
+  //  -- rcx                 : name
+  //  -- rsp[0]              : return address
+  //  -- rsp[(argc - n) * 4] : arg[n] (zero-based)
+  //  -- ...
+  //  -- rsp[(argc + 1) * 4] : receiver
+  // -----------------------------------
+
+  if (!CpuFeatures::IsSupported(SSE2)) {
+    return Handle<Code>::null();
+  }
+
+  CpuFeatureScope use_sse2(masm(), SSE2);
+
+  const int argc = arguments().immediate();
+
+  // If the object is not a JSObject or we got an unexpected number of
+  // arguments, bail out to the regular call.
+  if (!object->IsJSObject() || argc != 1) {
+    return Handle<Code>::null();
+  }
+
+  Label miss;
+  GenerateNameCheck(name, &miss);
+
+  if (cell.is_null()) {
+    __ movq(rdx, Operand(rsp, 2 * kPointerSize));
+
+    STATIC_ASSERT(kSmiTag == 0);
+    __ JumpIfSmi(rdx, &miss);
+
+ CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi,
+                    name, &miss);
+  } else {
+    ASSERT(cell->value() == *function);
+ GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
+                                &miss);
+    GenerateLoadFunctionFromCell(cell, function, &miss);
+  }
+
+  // Load the (only) argument into rax.
+  __ movq(rax, Operand(rsp, 1 * kPointerSize));
+
+  // Check if the argument is a smi.
+  Label smi;
+  STATIC_ASSERT(kSmiTag == 0);
+  __ JumpIfSmi(rax, &smi);
+
+  // Check if the argument is a heap number and load its value into xmm0.
+  Label slow;
+  __ CheckMap(rax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK);
+  __ movsd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset));
+
+ // Check if the argument is strictly positive. Note this also discards NaN.
+  __ xorpd(xmm1, xmm1);
+  __ ucomisd(xmm0, xmm1);
+  __ j(below_equal, &slow);
+
+  // Do a truncating conversion.
+  __ cvttsd2si(rax, xmm0);
+
+  // Checks for 0x80000000 which signals a failed conversion.
+  Label conversion_failure;
+  __ cmpl(rax, Immediate(0x80000000));
+  __ j(equal, &conversion_failure);
+
+  // Smi tag and return.
+  __ Integer32ToSmi(rax, rax);
+  __ bind(&smi);
+  __ ret(2 * kPointerSize);
+
+  // Check if the argument is < 2^kMantissaBits.
+  Label already_round;
+  __ bind(&conversion_failure);
+  int64_t kTwoMantissaBits= V8_INT64_C(0x4330000000000000);
+  __ movq(rbx, kTwoMantissaBits, RelocInfo::NONE64);
+  __ movq(xmm1, rbx);
+  __ ucomisd(xmm0, xmm1);
+  __ j(above_equal, &already_round);
+
+  // Save a copy of the argument.
+  __ movaps(xmm2, xmm0);
+
+  // Compute (argument + 2^kMantissaBits) - 2^kMantissaBits.
+  __ addsd(xmm0, xmm1);
+  __ subsd(xmm0, xmm1);
+
+  // Compare the argument and the tentative result to get the right mask:
+  //   if xmm2 < xmm0:
+  //     xmm2 = 1...1
+  //   else:
+  //     xmm2 = 0...0
+  __ cmpltsd(xmm2, xmm0);
+
+  // Subtract 1 if the argument was less than the tentative result.
+  int64_t kOne = V8_INT64_C(0x3ff0000000000000);
+  __ movq(rbx, kOne, RelocInfo::NONE64);
+  __ movq(xmm1, rbx);
+  __ andpd(xmm1, xmm2);
+  __ subsd(xmm0, xmm1);
+
+  // Return a new heap number.
+  __ AllocateHeapNumber(rax, rbx, &slow);
+  __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm0);
+  __ ret(2 * kPointerSize);
+
+  // Return the argument (when it's an already round heap number).
+  __ bind(&already_round);
+  __ movq(rax, Operand(rsp, 1 * kPointerSize));
+  __ ret(2 * kPointerSize);
+
+  // Tail call the full function. We do not have to patch the receiver
+  // because the function makes no use of it.
+  __ bind(&slow);
+  ParameterCount expected(function);
+  __ InvokeFunction(function, expected, arguments(),
+                    JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
+
+  __ bind(&miss);
+  // rcx: function name.
+  GenerateMissBranch();
+
+  // Return the generated code.
+  return GetCode(type, name);
 }


--
--
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