Reviewers: Søren Gjesse,

Description:
ARM: Implement DoPower in the lithium code generator.

Please review this at http://codereview.chromium.org/6532020/

SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge/src

Affected files:
  M src/arm/lithium-arm.h
  M src/arm/lithium-arm.cc
  M src/arm/lithium-codegen-arm.cc
  M src/arm/simulator-arm.cc
  M src/assembler.cc


Index: src/arm/lithium-arm.cc
diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
index 786ceeb3cac0b52afa0500645679d174ee08ca5d..1278e98f327451bc672141275973272cfd3df277 100644
--- a/src/arm/lithium-arm.cc
+++ b/src/arm/lithium-arm.cc
@@ -1418,8 +1418,18 @@ LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {


 LInstruction* LChunkBuilder::DoPower(HPower* instr) {
-  Abort("LPower instruction not implemented on ARM");
-  return NULL;
+  ASSERT(instr->representation().IsDouble());
+  // We call a C function for double power. It can't trigger a GC.
+  // We need to use fixed result register for the call.
+  Representation exponent_type = instr->right()->representation();
+  ASSERT(instr->left()->representation().IsDouble());
+  LOperand* left = UseFixedDouble(instr->left(), d1);
+  LOperand* right = exponent_type.IsDouble() ?
+      UseFixedDouble(instr->right(), d2) :
+      UseFixed(instr->right(), r0);
+  LPower* result = new LPower(left, right);
+  return MarkAsCall(DefineFixedDouble(result, d3), instr,
+                    CAN_DEOPTIMIZE_EAGERLY);
 }


Index: src/arm/lithium-arm.h
diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h
index 57338f16d5557cca4f7d8fe08fd6d29bca805b1e..bd625aa56046207fa6a9289686fc81cb3c682ca4 100644
--- a/src/arm/lithium-arm.h
+++ b/src/arm/lithium-arm.h
@@ -135,6 +135,7 @@ class LCodeGen;
   V(OuterContext)                               \
   V(Parameter)                                  \
   V(PixelArrayLength)                           \
+  V(Power)                                      \
   V(PushArgument)                               \
   V(RegExpLiteral)                              \
   V(Return)                                     \
@@ -1058,6 +1059,18 @@ class LAddI: public LTemplateInstruction<1, 2, 0> {
 };


+class LPower: public LTemplateInstruction<1, 2, 0> {
+ public:
+  LPower(LOperand* left, LOperand* right) {
+    inputs_[0] = left;
+    inputs_[1] = right;
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(Power, "power")
+  DECLARE_HYDROGEN_ACCESSOR(Power)
+};
+
+
 class LArithmeticD: public LTemplateInstruction<1, 2, 0> {
  public:
   LArithmeticD(Token::Value op, LOperand* left, LOperand* right)
Index: src/arm/lithium-codegen-arm.cc
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index 2c916f6ad67b847376a3656a5189f25d1cb0c18c..02e22b22e6acac2570b3df9fa5fe8791b875747c 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -2861,6 +2861,70 @@ void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) {
 }


+void LCodeGen::DoPower(LPower* instr) {
+  LOperand* left = instr->InputAt(0);
+  LOperand* right = instr->InputAt(1);
+  Register scratch = scratch0();
+  DoubleRegister result_reg = ToDoubleRegister(instr->result());
+ Representation exponent_type = instr->hydrogen()->right()->representation();
+  if (exponent_type.IsDouble()) {
+    // Save r0-r3 on the stack, prepare arguments and call C function.
+    __ stm(db_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit());
+    __ PrepareCallCFunction(4, scratch);
+    __ vmov(r0, r1, ToDoubleRegister(left));
+    __ vmov(r2, r3, ToDoubleRegister(right));
+    __ CallCFunction(ExternalReference::power_double_double_function(), 4);
+  } else if (exponent_type.IsInteger32()) {
+    ASSERT(ToRegister(right).is(r0));
+    // Save r0-r3 on the stack, prepare arguments and call C function.
+    __ stm(db_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit());
+    __ PrepareCallCFunction(4, scratch);
+    __ mov(r2, ToRegister(right));
+    __ vmov(r0, r1, ToDoubleRegister(left));
+    __ CallCFunction(ExternalReference::power_double_int_function(), 4);
+  } else {
+    ASSERT(exponent_type.IsTagged());
+    ASSERT(instr->hydrogen()->left()->representation().IsDouble());
+    ASSERT(CpuFeatures::IsSupported(VFP3));
+
+    Register right_reg = ToRegister(right);
+
+    // Check for smi on the right hand side.
+    Label non_smi, call;
+    __ tst(right_reg, Operand(kSmiTagMask));
+    __ b(ne, &non_smi);
+
+    // Untag smi and convert it to a double.
+    __ SmiUntag(right_reg);
+    SwVfpRegister single_scratch = double_scratch0().low();
+    __ vmov(single_scratch, right_reg);
+    __ vcvt_f64_s32(result_reg, single_scratch);
+    __ jmp(&call);
+
+    // Heap number map check.
+    __ bind(&non_smi);
+    __ ldr(scratch, FieldMemOperand(right_reg, HeapObject::kMapOffset));
+    __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
+    __ cmp(scratch, Operand(ip));
+    DeoptimizeIf(ne, instr->environment());
+    int32_t value_offset = HeapNumber::kValueOffset - kHeapObjectTag;
+    __ add(scratch, right_reg, Operand(value_offset), LeaveCC);
+    __ vldr(result_reg, scratch, 0);
+
+    // Save r0-r3 on the stack, prepare arguments and call C function.
+    __ bind(&call);
+    __ stm(db_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit());
+    __ PrepareCallCFunction(4, scratch);
+    __ vmov(r0, r1, ToDoubleRegister(left));
+    __ vmov(r2, r3, result_reg);
+    __ CallCFunction(ExternalReference::power_double_double_function(), 4);
+  }
+  // Store the result in the result register and restore r0-r3.
+  __ vmov(result_reg, r0, r1);
+  __ ldm(ia_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit());
+}
+
+
 void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) {
   switch (instr->op()) {
     case kMathAbs:
Index: src/arm/simulator-arm.cc
diff --git a/src/arm/simulator-arm.cc b/src/arm/simulator-arm.cc
index 8104747f14d49d861d86f97b5550c66e512a9a70..e96c05307f17d522fb3f66f8ab7e115dca907870 100644
--- a/src/arm/simulator-arm.cc
+++ b/src/arm/simulator-arm.cc
@@ -316,7 +316,7 @@ void Debugger::Debug() {
             }
             for (int i = 0; i < kNumVFPDoubleRegisters; i++) {
               dvalue = GetVFPDoubleRegisterValue(i);
-              PrintF("%3s: %f\n",
+              PrintF("%3s: %f \n",
                   VFPRegisters::Name(i, true), dvalue);
             }
           } else {
Index: src/assembler.cc
diff --git a/src/assembler.cc b/src/assembler.cc
index 42a61c2b8d0656cbcafe10167a4873d0df07821a..8094997b03d96fd87012fcb752d2fdf32c599ce1 100644
--- a/src/assembler.cc
+++ b/src/assembler.cc
@@ -850,12 +850,14 @@ double power_double_double(double x, double y) {


 ExternalReference ExternalReference::power_double_double_function() {
-  return ExternalReference(Redirect(FUNCTION_ADDR(power_double_double)));
+  return ExternalReference(Redirect(FUNCTION_ADDR(power_double_double),
+                                    FP_RETURN_CALL));
 }


 ExternalReference ExternalReference::power_double_int_function() {
-  return ExternalReference(Redirect(FUNCTION_ADDR(power_double_int)));
+  return ExternalReference(Redirect(FUNCTION_ADDR(power_double_int),
+                                    FP_RETURN_CALL));
 }




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

Reply via email to