Revision: 4618
Author: [email protected]
Date: Fri May  7 13:02:57 2010
Log: Add ldrd and strd instructions to the ARM port.  This is a
commit for [email protected].  See
http://codereview.chromium.org/568029 and
http://codereview.chromium.org/2019003
http://code.google.com/p/v8/source/detail?r=4618

Modified:
 /branches/bleeding_edge/AUTHORS
 /branches/bleeding_edge/src/arm/assembler-arm.cc
 /branches/bleeding_edge/src/arm/assembler-arm.h
 /branches/bleeding_edge/src/arm/codegen-arm.cc
 /branches/bleeding_edge/src/arm/disasm-arm.cc
 /branches/bleeding_edge/src/arm/simulator-arm.cc
 /branches/bleeding_edge/src/arm/simulator-arm.h

=======================================
--- /branches/bleeding_edge/AUTHORS     Thu Apr 22 10:28:43 2010
+++ /branches/bleeding_edge/AUTHORS     Fri May  7 13:02:57 2010
@@ -18,6 +18,7 @@
 Jay Freeman <[email protected]>
 Joel Stanley <[email protected]>
 John Jozwiak <[email protected]>
+Kun Zhang <[email protected]>
 Matt Hanselman <[email protected]>
 Martyn Capewell <[email protected]>
 Paolo Giarrusso <[email protected]>
=======================================
--- /branches/bleeding_edge/src/arm/assembler-arm.cc Tue Apr 27 04:16:05 2010 +++ /branches/bleeding_edge/src/arm/assembler-arm.cc Fri May 7 13:02:57 2010
@@ -1157,6 +1157,35 @@
 }


+void Assembler::ldrd(Register dst, const MemOperand& src, Condition cond) {
+  ASSERT(src.rm().is(no_reg));
+#ifdef CAN_USE_ARMV7_INSTRUCTIONS
+  addrmod3(cond | B7 | B6 | B4, dst, src);
+#else
+  ldr(dst, src, cond);
+  MemOperand src1(src);
+  src1.set_offset(src1.offset() + 4);
+  Register dst1(dst);
+  dst1.code_ = dst1.code_ + 1;
+  ldr(dst1, src1, cond);
+#endif
+}
+
+
+void Assembler::strd(Register src, const MemOperand& dst, Condition cond) {
+  ASSERT(dst.rm().is(no_reg));
+#ifdef CAN_USE_ARMV7_INSTRUCTIONS
+  addrmod3(cond | B7 | B6 | B5 | B4, src, dst);
+#else
+  str(src, dst, cond);
+  MemOperand dst1(dst);
+  dst1.set_offset(dst1.offset() + 4);
+  Register src1(src);
+  src1.code_ = src1.code_ + 1;
+  str(src1, dst1, cond);
+#endif
+}
+
 // Load/Store multiple instructions.
 void Assembler::ldm(BlockAddrMode am,
                     Register base,
=======================================
--- /branches/bleeding_edge/src/arm/assembler-arm.h     Tue Apr 27 02:09:51 2010
+++ /branches/bleeding_edge/src/arm/assembler-arm.h     Fri May  7 13:02:57 2010
@@ -448,6 +448,18 @@
   explicit MemOperand(Register rn, Register rm,
ShiftOp shift_op, int shift_imm, AddrMode am = Offset);

+  void set_offset(int32_t offset) {
+      ASSERT(rm_.is(no_reg));
+      offset_ = offset;
+  }
+
+  uint32_t offset() {
+      ASSERT(rm_.is(no_reg));
+      return offset_;
+  }
+
+  Register rm() const {return rm_;}
+
  private:
   Register rn_;  // base
   Register rm_;  // register offset
@@ -755,6 +767,8 @@
   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);

   // Load/Store multiple instructions
void ldm(BlockAddrMode am, Register base, RegList dst, Condition cond = al);
=======================================
--- /branches/bleeding_edge/src/arm/codegen-arm.cc      Fri May  7 07:06:55 2010
+++ /branches/bleeding_edge/src/arm/codegen-arm.cc      Fri May  7 13:02:57 2010
@@ -1486,8 +1486,7 @@
   // Then process it as a normal function call.
   __ ldr(r0, MemOperand(sp, 3 * kPointerSize));
   __ ldr(r1, MemOperand(sp, 2 * kPointerSize));
-  __ str(r0, MemOperand(sp, 2 * kPointerSize));
-  __ str(r1, MemOperand(sp, 3 * kPointerSize));
+  __ strd(r0, MemOperand(sp, 2 * kPointerSize));

   CallFunctionStub call_function(2, NOT_IN_LOOP, NO_CALL_FUNCTION_FLAGS);
   frame_->CallStub(&call_function, 3);
@@ -2279,8 +2278,8 @@
   node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
   node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);

-  __ ldr(r0, frame_->ElementAt(0));  // load the current count
-  __ ldr(r1, frame_->ElementAt(1));  // load the length
+  // Load the current count to r0, load the length to r1.
+  __ ldrd(r0, frame_->ElementAt(0));
   __ cmp(r0, r1);  // compare to the array length
   node->break_target()->Branch(hs);

@@ -6310,8 +6309,7 @@
     ConvertToDoubleStub stub1(r3, r2, r7, r6);
     __ Call(stub1.GetCode(), RelocInfo::CODE_TARGET);
     // Load rhs to a double in r0, r1.
- __ ldr(r1, FieldMemOperand(r0, HeapNumber::kValueOffset + kPointerSize));
-    __ ldr(r0, FieldMemOperand(r0, HeapNumber::kValueOffset));
+    __ ldrd(r0, FieldMemOperand(r0, HeapNumber::kValueOffset));
     __ pop(lr);
   }

@@ -6346,8 +6344,7 @@
   } else {
     __ push(lr);
     // Load lhs to a double in r2, r3.
- __ ldr(r3, FieldMemOperand(r1, HeapNumber::kValueOffset + kPointerSize));
-    __ ldr(r2, FieldMemOperand(r1, HeapNumber::kValueOffset));
+    __ ldrd(r2, FieldMemOperand(r1, HeapNumber::kValueOffset));
     // Convert rhs to a double in r0, r1.
     __ mov(r7, Operand(r0));
     ConvertToDoubleStub stub2(r1, r0, r7, r6);
@@ -6511,10 +6508,8 @@
     __ sub(r7, r1, Operand(kHeapObjectTag));
     __ vldr(d7, r7, HeapNumber::kValueOffset);
   } else {
-    __ ldr(r2, FieldMemOperand(r1, HeapNumber::kValueOffset));
- __ ldr(r3, FieldMemOperand(r1, HeapNumber::kValueOffset + kPointerSize)); - __ ldr(r1, FieldMemOperand(r0, HeapNumber::kValueOffset + kPointerSize));
-    __ ldr(r0, FieldMemOperand(r0, HeapNumber::kValueOffset));
+    __ ldrd(r2, FieldMemOperand(r1, HeapNumber::kValueOffset));
+    __ ldrd(r0, FieldMemOperand(r0, HeapNumber::kValueOffset));
   }
   __ jmp(both_loaded_as_doubles);
 }
@@ -6891,8 +6886,7 @@
       __ vldr(d7, r7, HeapNumber::kValueOffset);
     } else {
       // Calling convention says that second double is in r2 and r3.
-      __ ldr(r2, FieldMemOperand(r0, HeapNumber::kValueOffset));
-      __ ldr(r3, FieldMemOperand(r0, HeapNumber::kValueOffset + 4));
+      __ ldrd(r2, FieldMemOperand(r0, HeapNumber::kValueOffset));
     }
     __ jmp(&finished_loading_r0);
     __ bind(&r0_is_smi);
@@ -6944,8 +6938,7 @@
       __ vldr(d6, r7, HeapNumber::kValueOffset);
     } else {
       // Calling convention says that first double is in r0 and r1.
-      __ ldr(r0, FieldMemOperand(r1, HeapNumber::kValueOffset));
-      __ ldr(r1, FieldMemOperand(r1, HeapNumber::kValueOffset + 4));
+      __ ldrd(r0, FieldMemOperand(r1, HeapNumber::kValueOffset));
     }
     __ jmp(&finished_loading_r1);
     __ bind(&r1_is_smi);
@@ -7016,8 +7009,7 @@
       __ stc(p1, cr8, MemOperand(r4, HeapNumber::kValueOffset));
   #else
       // Double returned in registers 0 and 1.
-      __ str(r0, FieldMemOperand(r5, HeapNumber::kValueOffset));
-      __ str(r1, FieldMemOperand(r5, HeapNumber::kValueOffset + 4));
+      __ strd(r0, FieldMemOperand(r5, HeapNumber::kValueOffset));
   #endif
       __ mov(r0, Operand(r5));
       // And we are done.
=======================================
--- /branches/bleeding_edge/src/arm/disasm-arm.cc       Wed Apr 21 02:45:06 2010
+++ /branches/bleeding_edge/src/arm/disasm-arm.cc       Fri May  7 13:02:57 2010
@@ -418,6 +418,12 @@
         ASSERT(STRING_STARTS_WITH(format, "memop"));
         if (instr->HasL()) {
           Print("ldr");
+        } else if ((instr->Bits(27, 25) == 0) && (instr->Bit(20) == 0)) {
+          if (instr->Bits(7, 4) == 0xf) {
+            Print("strd");
+          } else {
+            Print("ldrd");
+          }
         } else {
           Print("str");
         }
@@ -614,6 +620,47 @@
       } else {
         Unknown(instr);  // not used by V8
       }
+ } else if ((instr->Bit(20) == 0) && ((instr->Bits(7, 4) & 0xd) == 0xd)) {
+      // ldrd, strd
+      switch (instr->PUField()) {
+        case 0: {
+          if (instr->Bit(22) == 0) {
+            Format(instr, "'memop'cond's 'rd, ['rn], -'rm");
+          } else {
+            Format(instr, "'memop'cond's 'rd, ['rn], #-'off8");
+          }
+          break;
+        }
+        case 1: {
+          if (instr->Bit(22) == 0) {
+            Format(instr, "'memop'cond's 'rd, ['rn], +'rm");
+          } else {
+            Format(instr, "'memop'cond's 'rd, ['rn], #+'off8");
+          }
+          break;
+        }
+        case 2: {
+          if (instr->Bit(22) == 0) {
+            Format(instr, "'memop'cond's 'rd, ['rn, -'rm]'w");
+          } else {
+            Format(instr, "'memop'cond's 'rd, ['rn, #-'off8]'w");
+          }
+          break;
+        }
+        case 3: {
+          if (instr->Bit(22) == 0) {
+            Format(instr, "'memop'cond's 'rd, ['rn, +'rm]'w");
+          } else {
+            Format(instr, "'memop'cond's 'rd, ['rn, #+'off8]'w");
+          }
+          break;
+        }
+        default: {
+          // The PU field is a 2-bit field.
+          UNREACHABLE();
+          break;
+        }
+      }
     } else {
       // extra load/store instructions
       switch (instr->PUField()) {
=======================================
--- /branches/bleeding_edge/src/arm/simulator-arm.cc Thu May 6 05:49:12 2010 +++ /branches/bleeding_edge/src/arm/simulator-arm.cc Fri May 7 13:02:57 2010
@@ -726,6 +726,13 @@
   ASSERT((reg >= 0) && (reg < num_registers));
   return registers_[reg] + ((reg == pc) ? Instr::kPCReadOffset : 0);
 }
+
+
+void Simulator::set_dw_register(int dreg, const int* dbl) {
+  ASSERT((dreg >= 0) && (dreg < num_d_registers));
+  registers_[dreg] = dbl[0];
+  registers_[dreg + 1] = dbl[1];
+}


 // Raw access to the PC register.
@@ -887,7 +894,7 @@
     intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
     return *ptr;
   }
-  PrintF("Unaligned read at 0x%08x\n", addr);
+  PrintF("Unaligned read at 0x%08x, pc=%p\n", addr, instr);
   UNIMPLEMENTED();
   return 0;
 #endif
@@ -999,6 +1006,41 @@
   int8_t* ptr = reinterpret_cast<int8_t*>(addr);
   *ptr = value;
 }
+
+
+int32_t* Simulator::ReadDW(int32_t addr) {
+#if V8_TARGET_CAN_READ_UNALIGNED
+  int32_t* ptr = reinterpret_cast<int32_t*>(addr);
+  return ptr;
+#else
+  if ((addr & 3) == 0) {
+    int32_t* ptr = reinterpret_cast<int32_t*>(addr);
+    return ptr;
+  }
+  PrintF("Unaligned read at 0x%08x\n", addr);
+  UNIMPLEMENTED();
+  return 0;
+#endif
+}
+
+
+void Simulator::WriteDW(int32_t addr, int32_t value1, int32_t value2) {
+#if V8_TARGET_CAN_READ_UNALIGNED
+  int32_t* ptr = reinterpret_cast<int32_t*>(addr);
+  *ptr++ = value1;
+  *ptr = value2;
+  return;
+#else
+  if ((addr & 3) == 0) {
+    int32_t* ptr = reinterpret_cast<int32_t*>(addr);
+    *ptr++ = value1;
+    *ptr = value2;
+    return;
+  }
+  PrintF("Unaligned write at 0x%08x\n", addr);
+  UNIMPLEMENTED();
+#endif
+}


// Returns the limit of the stack area to enable checking for stack overflows.
@@ -1628,7 +1670,19 @@
           }
         }
       }
-      if (instr->HasH()) {
+      if (((instr->Bits(7, 4) & 0xd) == 0xd) && (instr->Bit(20) == 0)) {
+        ASSERT((rd % 2) == 0);
+        if (instr->HasH()) {
+          // The strd instruction.
+          int32_t value1 = get_register(rd);
+          int32_t value2 = get_register(rd+1);
+          WriteDW(addr, value1, value2);
+        } else {
+          // The ldrd instruction.
+          int* rn_data = ReadDW(addr);
+          set_dw_register(rd, rn_data);
+        }
+      } else if (instr->HasH()) {
         if (instr->HasSign()) {
           if (instr->HasL()) {
             int16_t val = ReadH(addr, instr);
=======================================
--- /branches/bleeding_edge/src/arm/simulator-arm.h     Thu Apr 22 05:41:10 2010
+++ /branches/bleeding_edge/src/arm/simulator-arm.h     Fri May  7 13:02:57 2010
@@ -159,6 +159,7 @@
   // instruction.
   void set_register(int reg, int32_t value);
   int32_t get_register(int reg) const;
+  void set_dw_register(int dreg, const int* dbl);

   // Support for VFP.
   void set_s_register(int reg, unsigned int value);
@@ -252,6 +253,9 @@
   inline int ReadW(int32_t addr, Instr* instr);
   inline void WriteW(int32_t addr, int value, Instr* instr);

+  int32_t* ReadDW(int32_t addr);
+  void WriteDW(int32_t addr, int32_t value1, int32_t value2);
+
   // Executing is handled based on the instruction type.
void DecodeType01(Instr* instr); // both type 0 and type 1 rolled into one
   void DecodeType2(Instr* instr);

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

Reply via email to