Make ldrd and strd instructions take two register arguments
authorsgjesse@chromium.org <sgjesse@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 26 May 2010 09:43:54 +0000 (09:43 +0000)
committersgjesse@chromium.org <sgjesse@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 26 May 2010 09:43:54 +0000 (09:43 +0000)
Review URL: http://codereview.chromium.org/2122021

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4724 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/arm/assembler-arm.cc
src/arm/assembler-arm.h
src/arm/codegen-arm.cc
src/arm/full-codegen-arm.cc

index dba62e6..a3966a2 100644 (file)
@@ -1363,39 +1363,45 @@ void Assembler::ldrsh(Register dst, const MemOperand& src, Condition cond) {
 }
 
 
-void Assembler::ldrd(Register dst, const MemOperand& src, Condition cond) {
+void Assembler::ldrd(Register dst1,
+                     Register dst2,
+                     const MemOperand& src, Condition cond) {
   ASSERT(src.rm().is(no_reg));
+  ASSERT(!dst1.is(lr));  // r14.
+  ASSERT_EQ(0, dst1.code() % 2);
+  ASSERT_EQ(dst1.code() + 1, dst2.code());
 #ifdef CAN_USE_ARMV7_INSTRUCTIONS
-  addrmod3(cond | B7 | B6 | B4, dst, src);
+  addrmod3(cond | B7 | B6 | B4, dst1, src);
 #else
   // Generate two ldr instructions if ldrd is not available.
-  MemOperand src1(src);
-  src1.set_offset(src1.offset() + 4);
-  Register dst1(dst);
-  dst1.set_code(dst1.code() + 1);
-  if (dst.is(src.rn())) {
-    ldr(dst1, src1, cond);
-    ldr(dst, src, cond);
+  MemOperand src2(src);
+  src2.set_offset(src2.offset() + 4);
+  if (dst1.is(src.rn())) {
+    ldr(dst2, src2, cond);
+    ldr(dst1, src, cond);
   } else {
-    ldr(dst, src, cond);
-    ldr(dst1, src1, cond);
+    ldr(dst1, src, cond);
+    ldr(dst2, src2, cond);
   }
 #endif
 }
 
 
-void Assembler::strd(Register src, const MemOperand& dst, Condition cond) {
+void Assembler::strd(Register src1,
+                     Register src2,
+                     const MemOperand& dst, Condition cond) {
   ASSERT(dst.rm().is(no_reg));
+  ASSERT(!src1.is(lr));  // r14.
+  ASSERT_EQ(0, src1.code() % 2);
+  ASSERT_EQ(src1.code() + 1, src2.code());
 #ifdef CAN_USE_ARMV7_INSTRUCTIONS
-  addrmod3(cond | B7 | B6 | B5 | B4, src, dst);
+  addrmod3(cond | B7 | B6 | B5 | B4, src1, dst);
 #else
   // Generate two str instructions if strd is not available.
-  MemOperand dst1(dst);
-  dst1.set_offset(dst1.offset() + 4);
-  Register src1(src);
-  src1.set_code(src1.code() + 1);
-  str(src, dst, cond);
-  str(src1, dst1, cond);
+  MemOperand dst2(dst);
+  dst2.set_offset(dst2.offset() + 4);
+  str(src1, dst, cond);
+  str(src2, dst2, cond);
 #endif
 }
 
index 5a5d64b..a1b98f6 100644 (file)
@@ -773,8 +773,12 @@ class Assembler : public Malloced {
   void strh(Register src, const MemOperand& dst, Condition cond = al);
   void ldrsb(Register dst, const MemOperand& src, Condition cond = al);
   void ldrsh(Register dst, const MemOperand& src, Condition cond = al);
-  void ldrd(Register dst, const MemOperand& src, Condition cond = al);
-  void strd(Register src, const MemOperand& dst, Condition cond = al);
+  void ldrd(Register dst1,
+            Register dst2,
+            const MemOperand& src, Condition cond = al);
+  void strd(Register src1,
+            Register src2,
+            const MemOperand& dst, Condition cond = al);
 
   // Load/Store multiple instructions
   void ldm(BlockAddrMode am, Register base, RegList dst, Condition cond = al);
index 3e628de..062f955 100644 (file)
@@ -1514,7 +1514,7 @@ void CodeGenerator::CallApplyLazy(Expression* applicand,
   // Then process it as a normal function call.
   __ ldr(r0, MemOperand(sp, 3 * kPointerSize));
   __ ldr(r1, MemOperand(sp, 2 * kPointerSize));
-  __ strd(r0, MemOperand(sp, 2 * kPointerSize));
+  __ strd(r0, r1, MemOperand(sp, 2 * kPointerSize));
 
   CallFunctionStub call_function(2, NOT_IN_LOOP, NO_CALL_FUNCTION_FLAGS);
   frame_->CallStub(&call_function, 3);
@@ -2307,7 +2307,7 @@ void CodeGenerator::VisitForInStatement(ForInStatement* node) {
   node->continue_target()->SetExpectedHeight();
 
   // Load the current count to r0, load the length to r1.
-  __ ldrd(r0, frame_->ElementAt(0));
+  __ ldrd(r0, r1, frame_->ElementAt(0));
   __ cmp(r0, r1);  // compare to the array length
   node->break_target()->Branch(hs);
 
@@ -6379,7 +6379,7 @@ static void EmitSmiNonsmiComparison(MacroAssembler* masm,
     ConvertToDoubleStub stub1(r3, r2, r7, r6);
     __ Call(stub1.GetCode(), RelocInfo::CODE_TARGET);
     // Load rhs to a double in r0, r1.
-    __ ldrd(r0, FieldMemOperand(r0, HeapNumber::kValueOffset));
+    __ ldrd(r0, r1, FieldMemOperand(r0, HeapNumber::kValueOffset));
     __ pop(lr);
   }
 
@@ -6414,7 +6414,7 @@ static void EmitSmiNonsmiComparison(MacroAssembler* masm,
   } else {
     __ push(lr);
     // Load lhs to a double in r2, r3.
-    __ ldrd(r2, FieldMemOperand(r1, HeapNumber::kValueOffset));
+    __ ldrd(r2, r3, FieldMemOperand(r1, HeapNumber::kValueOffset));
     // Convert rhs to a double in r0, r1.
     __ mov(r7, Operand(r0));
     ConvertToDoubleStub stub2(r1, r0, r7, r6);
@@ -6578,8 +6578,8 @@ static void EmitCheckForTwoHeapNumbers(MacroAssembler* masm,
     __ sub(r7, r1, Operand(kHeapObjectTag));
     __ vldr(d7, r7, HeapNumber::kValueOffset);
   } else {
-    __ ldrd(r2, FieldMemOperand(r1, HeapNumber::kValueOffset));
-    __ ldrd(r0, FieldMemOperand(r0, HeapNumber::kValueOffset));
+    __ ldrd(r2, r3, FieldMemOperand(r1, HeapNumber::kValueOffset));
+    __ ldrd(r0, r1, FieldMemOperand(r0, HeapNumber::kValueOffset));
   }
   __ jmp(both_loaded_as_doubles);
 }
@@ -6956,7 +6956,7 @@ void GenericBinaryOpStub::HandleBinaryOpSlowCases(
       __ vldr(d7, r7, HeapNumber::kValueOffset);
     } else {
       // Calling convention says that second double is in r2 and r3.
-      __ ldrd(r2, FieldMemOperand(r0, HeapNumber::kValueOffset));
+      __ ldrd(r2, r3, FieldMemOperand(r0, HeapNumber::kValueOffset));
     }
     __ jmp(&finished_loading_r0);
     __ bind(&r0_is_smi);
@@ -7008,7 +7008,7 @@ void GenericBinaryOpStub::HandleBinaryOpSlowCases(
       __ vldr(d6, r7, HeapNumber::kValueOffset);
     } else {
       // Calling convention says that first double is in r0 and r1.
-      __ ldrd(r0, FieldMemOperand(r1, HeapNumber::kValueOffset));
+      __ ldrd(r0, r1, FieldMemOperand(r1, HeapNumber::kValueOffset));
     }
     __ jmp(&finished_loading_r1);
     __ bind(&r1_is_smi);
@@ -7079,7 +7079,7 @@ void GenericBinaryOpStub::HandleBinaryOpSlowCases(
       __ stc(p1, cr8, MemOperand(r4, HeapNumber::kValueOffset));
   #else
       // Double returned in registers 0 and 1.
-      __ strd(r0, FieldMemOperand(r5, HeapNumber::kValueOffset));
+      __ strd(r0, r1, FieldMemOperand(r5, HeapNumber::kValueOffset));
   #endif
       __ mov(r0, Operand(r5));
       // And we are done.
index 57e7a4f..37fa6c9 100644 (file)
@@ -935,7 +935,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
   // Generate code for doing the condition check.
   __ bind(&loop);
   // Load the current count to r0, load the length to r1.
-  __ ldrd(r0, MemOperand(sp, 0 * kPointerSize));
+  __ ldrd(r0, r1, MemOperand(sp, 0 * kPointerSize));
   __ cmp(r0, r1);  // Compare to the array length.
   __ b(hs, loop_statement.break_target());