Revision: 6531
Author: [email protected]
Date: Mon Jan 31 02:16:28 2011
Log: ARM: Add support for DoMathAbs with double inputs.

Adds vabs instruction to simulator, assembler, disassembler and tests.

BUG=none
TEST=Added to cctest.

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

Modified:
 /branches/bleeding_edge/src/arm/assembler-arm.cc
 /branches/bleeding_edge/src/arm/assembler-arm.h
 /branches/bleeding_edge/src/arm/disasm-arm.cc
 /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc
 /branches/bleeding_edge/src/arm/macro-assembler-arm.cc
 /branches/bleeding_edge/src/arm/macro-assembler-arm.h
 /branches/bleeding_edge/src/arm/simulator-arm.cc
 /branches/bleeding_edge/test/cctest/test-assembler-arm.cc
 /branches/bleeding_edge/test/cctest/test-disasm-arm.cc

=======================================
--- /branches/bleeding_edge/src/arm/assembler-arm.cc Wed Jan 26 00:32:54 2011 +++ /branches/bleeding_edge/src/arm/assembler-arm.cc Mon Jan 31 02:16:28 2011
@@ -2226,6 +2226,14 @@
   ASSERT(CpuFeatures::IsEnabled(VFP3));
   emit(EncodeVCVT(F32, dst.code(), F64, src.code(), mode, cond));
 }
+
+
+void Assembler::vabs(const DwVfpRegister dst,
+                     const DwVfpRegister src,
+                     const Condition cond) {
+  emit(cond | 0xE*B24 | 0xB*B20 | dst.code()*B12 |
+       0x5*B9 | B8 | 0x3*B6 | src.code());
+}


 void Assembler::vadd(const DwVfpRegister dst,
=======================================
--- /branches/bleeding_edge/src/arm/assembler-arm.h     Wed Jan 26 00:32:54 2011
+++ /branches/bleeding_edge/src/arm/assembler-arm.h     Mon Jan 31 02:16:28 2011
@@ -975,6 +975,9 @@
                     ConversionMode mode = RoundToZero,
                     const Condition cond = al);

+  void vabs(const DwVfpRegister dst,
+            const DwVfpRegister src,
+            const Condition cond = al);
   void vadd(const DwVfpRegister dst,
             const DwVfpRegister src1,
             const DwVfpRegister src2,
=======================================
--- /branches/bleeding_edge/src/arm/disasm-arm.cc       Wed Jan 26 00:32:54 2011
+++ /branches/bleeding_edge/src/arm/disasm-arm.cc       Mon Jan 31 02:16:28 2011
@@ -1064,6 +1064,9 @@
         } else {
           Format(instr, "vmov.f32'cond 'Sd, 'Sm");
         }
+ } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) {
+        // vabs
+        Format(instr, "vabs'cond 'Dd, 'Dm");
} else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) {
         DecodeVCVTBetweenDoubleAndSingle(instr);
} else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) {
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Thu Jan 27 00:35:39 2011 +++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Mon Jan 31 02:16:28 2011
@@ -1174,8 +1174,7 @@
                                          0,
Safepoint::kNoDeoptimizationIndex);
   // Overwrite the stored value of r0 with the result of the stub.
-  __ str(r0, MemOperand(sp, DwVfpRegister::kNumAllocatableRegisters *
-                        kDoubleSize));
+  __ StoreToSafepointRegistersAndDoublesSlot(r0);
   __ PopSafepointRegistersAndDoubles();
 }

@@ -2525,6 +2524,7 @@


void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) {
+  ASSERT(instr->InputAt(0)->Equals(instr->result()));
   Register input = ToRegister(instr->InputAt(0));
   Register scratch = scratch0();

@@ -2535,28 +2535,32 @@
   DeoptimizeIf(ne, instr->environment());

   Label done;
-
-  Label negative;
-  __ ldr(scratch, FieldMemOperand(input, HeapNumber::kExponentOffset));
+  Register exponent = scratch0();
+  scratch = no_reg;
+  __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset));
   // Check the sign of the argument. If the argument is positive, just
   // return it. We do not need to patch the stack since |input| and
-  // |result| are the same register and |input| will be restored
+  // |result| are the same register and |input| would be restored
   // unchanged by popping safepoint registers.
-  __ tst(scratch, Operand(HeapNumber::kSignMask));
-  __ b(ne, &negative);
-  __ jmp(&done);
-
-  __ bind(&negative);
+  __ tst(exponent, Operand(HeapNumber::kSignMask));
+  __ b(eq, &done);
+
+  // Input is negative. Reverse its sign.
   // Preserve the value of all registers.
   __ PushSafepointRegisters();

-  Register tmp = input.is(r0) ? r1 : r0;
-  Register tmp2 = input.is(r2) ? r3 : r2;
-  Register tmp3 = input.is(r4) ? r5 : r4;
+  // Registers were saved at the safepoint, so we can use
+  // many scratch registers.
+  Register tmp1 = input.is(r1) ? r0 : r1;
+  Register tmp2 = input.is(r2) ? r0 : r2;
+  Register tmp3 = input.is(r3) ? r0 : r3;
+  Register tmp4 = input.is(r4) ? r0 : r4;
+
+  // exponent: floating point exponent value.

   Label allocated, slow;
-  __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex);
-  __ AllocateHeapNumber(tmp, tmp2, tmp3, scratch, &slow);
+  __ LoadRoot(tmp4, Heap::kHeapNumberMapRootIndex);
+  __ AllocateHeapNumber(tmp1, tmp2, tmp3, tmp4, &slow);
   __ b(&allocated);

   // Slow case: Call the runtime system to do the number allocation.
@@ -2566,20 +2570,20 @@
   RecordSafepointWithRegisters(
       instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex);
   // Set the pointer to the new heap number in tmp.
-  if (!tmp.is(r0)) __ mov(tmp, Operand(r0));
-
+  if (!tmp1.is(r0)) __ mov(tmp1, Operand(r0));
   // Restore input_reg after call to runtime.
-  MemOperand input_register_slot = masm()->SafepointRegisterSlot(input);
-  __ ldr(input, input_register_slot);
+  __ LoadFromSafepointRegisterSlot(input);
+  __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset));

   __ bind(&allocated);
-  __ ldr(tmp2, FieldMemOperand(input, HeapNumber::kExponentOffset));
-  __ bic(tmp2, tmp2, Operand(HeapNumber::kSignMask));
-  __ str(tmp2, FieldMemOperand(tmp, HeapNumber::kExponentOffset));
+  // exponent: floating point exponent value.
+  // tmp1: allocated heap number.
+  __ bic(exponent, exponent, Operand(HeapNumber::kSignMask));
+  __ str(exponent, FieldMemOperand(tmp1, HeapNumber::kExponentOffset));
   __ ldr(tmp2, FieldMemOperand(input, HeapNumber::kMantissaOffset));
-  __ str(tmp2, FieldMemOperand(tmp, HeapNumber::kMantissaOffset));
-
-  __ str(tmp, input_register_slot);
+  __ str(tmp2, FieldMemOperand(tmp1, HeapNumber::kMantissaOffset));
+
+  __ str(tmp1, masm()->SafepointRegisterSlot(input));
   __ PopSafepointRegisters();

   __ bind(&done);
@@ -2587,15 +2591,14 @@


 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) {
-  Label is_positive;
-  uint32_t kSignMask = 0x80000000u;
   Register input = ToRegister(instr->InputAt(0));
-  __ tst(input, Operand(kSignMask));
-  __ b(eq, &is_positive);
-  __ rsb(input, input, Operand(0), SetCC);
+  __ cmp(input, Operand(0));
+  // We can make rsb conditional because the previous cmp instruction
+  // will clear the V (overflow) flag and rsb won't set this flag
+  // if input is positive.
+  __ rsb(input, input, Operand(0), SetCC, mi);
   // Deoptimize on overflow.
   DeoptimizeIf(vs, instr->environment());
-  __ bind(&is_positive);
 }


@@ -2617,8 +2620,7 @@
   Representation r = instr->hydrogen()->value()->representation();
   if (r.IsDouble()) {
     DwVfpRegister input = ToDoubleRegister(instr->InputAt(0));
-    // __ vabs(input, input);
-    Abort("Double DoMathAbs unimplemented");
+    __ vabs(input, input);
   } else if (r.IsInteger32()) {
     EmitIntegerMathAbs(instr);
   } else {
=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Wed Jan 26 00:32:54 2011 +++ /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Mon Jan 31 02:16:28 2011
@@ -485,9 +485,19 @@
   PopSafepointRegisters();
 }

+void MacroAssembler::StoreToSafepointRegistersAndDoublesSlot(Register reg) {
+  str(reg, SafepointRegistersAndDoublesSlot(reg));
+}
+
+
 void MacroAssembler::StoreToSafepointRegisterSlot(Register reg) {
   str(reg, SafepointRegisterSlot(reg));
 }
+
+
+void MacroAssembler::LoadFromSafepointRegisterSlot(Register reg) {
+  ldr(reg, SafepointRegisterSlot(reg));
+}


 int MacroAssembler::SafepointRegisterStackIndex(int reg_code) {
@@ -501,6 +511,14 @@
 MemOperand MacroAssembler::SafepointRegisterSlot(Register reg) {
return MemOperand(sp, SafepointRegisterStackIndex(reg.code()) * kPointerSize);
 }
+
+
+MemOperand MacroAssembler::SafepointRegistersAndDoublesSlot(Register reg) {
+  // General purpose registers are pushed last on the stack.
+  int doubles_size = DwVfpRegister::kNumAllocatableRegisters * kDoubleSize;
+ int register_offset = SafepointRegisterStackIndex(reg.code()) * kPointerSize;
+  return MemOperand(sp, doubles_size + register_offset);
+}


 void MacroAssembler::Ldrd(Register dst1, Register dst2,
=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.h Wed Jan 26 00:32:54 2011 +++ /branches/bleeding_edge/src/arm/macro-assembler-arm.h Mon Jan 31 02:16:28 2011
@@ -235,8 +235,11 @@
   void PushSafepointRegistersAndDoubles();
   void PopSafepointRegistersAndDoubles();
   void StoreToSafepointRegisterSlot(Register reg);
+  void StoreToSafepointRegistersAndDoublesSlot(Register reg);
+  void LoadFromSafepointRegisterSlot(Register reg);
   static int SafepointRegisterStackIndex(int reg_code);
   static MemOperand SafepointRegisterSlot(Register reg);
+  static MemOperand SafepointRegistersAndDoublesSlot(Register reg);

   // Load two consecutive registers with two consecutive memory locations.
   void Ldrd(Register dst1,
=======================================
--- /branches/bleeding_edge/src/arm/simulator-arm.cc Wed Jan 26 00:32:54 2011 +++ /branches/bleeding_edge/src/arm/simulator-arm.cc Mon Jan 31 02:16:28 2011
@@ -2445,6 +2445,11 @@
           int d = instr->VFPDRegValue(kSinglePrecision);
           set_s_register_from_float(d, get_float_from_s_register(m));
         }
+ } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) {
+        // vabs
+        double dm_value = get_double_from_d_register(vm);
+        double dd_value = fabs(dm_value);
+        set_d_register_from_double(vd, dd_value);
} else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) {
         DecodeVCVTBetweenDoubleAndSingle(instr);
} else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) {
=======================================
--- /branches/bleeding_edge/test/cctest/test-assembler-arm.cc Wed Jan 26 01:52:25 2011 +++ /branches/bleeding_edge/test/cctest/test-assembler-arm.cc Mon Jan 31 02:16:28 2011
@@ -229,6 +229,8 @@
     double d;
     double e;
     double f;
+    double g;
+    double h;
     int i;
     float x;
     float y;
@@ -286,6 +288,15 @@
     __ vmov(s31, lr);
     __ vcvt_f64_s32(d4, s31);
     __ vstr(d4, r4, OFFSET_OF(T, f));
+
+    // Test vabs.
+    __ vldr(d1, r4, OFFSET_OF(T, g));
+    __ vabs(d0, d1);
+    __ vstr(d0, r4, OFFSET_OF(T, g));
+    __ vldr(d2, r4, OFFSET_OF(T, h));
+    __ vabs(d0, d2);
+    __ vstr(d0, r4, OFFSET_OF(T, h));
+
     __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());

     CodeDesc desc;
@@ -305,6 +316,8 @@
     t.d = 0.0;
     t.e = 0.0;
     t.f = 0.0;
+    t.g = -2718.2818;
+    t.h = 31415926.5;
     t.i = 0;
     t.x = 4.5;
     t.y = 9.0;
@@ -313,6 +326,8 @@
     CHECK_EQ(4.5, t.y);
     CHECK_EQ(9.0, t.x);
     CHECK_EQ(2, t.i);
+    CHECK_EQ(2718.2818, t.g);
+    CHECK_EQ(31415926.5, t.h);
     CHECK_EQ(42.0, t.f);
     CHECK_EQ(1.0, t.e);
     CHECK_EQ(1.000000059604644775390625, t.d);
=======================================
--- /branches/bleeding_edge/test/cctest/test-disasm-arm.cc Tue Dec 7 03:01:02 2010 +++ /branches/bleeding_edge/test/cctest/test-disasm-arm.cc Mon Jan 31 02:16:28 2011
@@ -435,6 +435,11 @@
     COMPARE(vmov(s31, r10),
             "ee0faa90       vmov s31, r10");

+    COMPARE(vabs(d0, d1),
+            "eeb00bc1       vabs d0, d1");
+    COMPARE(vabs(d3, d4, mi),
+            "4eb03bc4       vabsmi d3, d4");
+
     COMPARE(vadd(d0, d1, d2),
             "ee310b02       vadd.f64 d0, d1, d2");
     COMPARE(vadd(d3, d4, d5, mi),

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

Reply via email to