Upstream version 11.40.271.0
[platform/framework/web/crosswalk.git] / src / v8 / src / arm / assembler-arm-inl.h
index 1cfe34b..d8228a2 100644 (file)
@@ -48,6 +48,7 @@ namespace internal {
 
 
 bool CpuFeatures::SupportsCrankshaft() { return IsSupported(VFP3); }
+bool CpuFeatures::SupportsSIMD128InCrankshaft() { return false; }
 
 
 int Register::NumAllocatableRegisters() {
@@ -70,6 +71,12 @@ int DwVfpRegister::NumAllocatableRegisters() {
 }
 
 
+// static
+int DwVfpRegister::NumAllocatableAliasedRegisters() {
+  return LowDwVfpRegister::kMaxNumLowRegisters - kNumReservedRegisters;
+}
+
+
 int DwVfpRegister::ToAllocationIndex(DwVfpRegister reg) {
   DCHECK(!reg.is(kDoubleRegZero));
   DCHECK(!reg.is(kScratchDoubleReg));
@@ -423,36 +430,58 @@ void Assembler::emit(Instr x) {
 Address Assembler::target_address_from_return_address(Address pc) {
   // Returns the address of the call target from the return address that will
   // be returned to after a call.
-  // Call sequence on V7 or later is :
+  // Call sequence on V7 or later is:
   //  movw  ip, #... @ call address low 16
   //  movt  ip, #... @ call address high 16
   //  blx   ip
   //                      @ return address
-  // Or pre-V7 or cases that need frequent patching, the address is in the
+  // For V6 when the constant pool is unavailable, it is:
+  //  mov  ip, #...     @ call address low 8
+  //  orr  ip, ip, #... @ call address 2nd 8
+  //  orr  ip, ip, #... @ call address 3rd 8
+  //  orr  ip, ip, #... @ call address high 8
+  //  blx   ip
+  //                      @ return address
+  // In cases that need frequent patching, the address is in the
   // constant pool.  It could be a small constant pool load:
   //  ldr   ip, [pc / pp, #...] @ call address
   //  blx   ip
   //                      @ return address
-  // Or an extended constant pool load:
+  // Or an extended constant pool load (ARMv7):
   //  movw  ip, #...
   //  movt  ip, #...
   //  ldr   ip, [pc, ip]  @ call address
   //  blx   ip
   //                      @ return address
+  // Or an extended constant pool load (ARMv6):
+  //  mov  ip, #...
+  //  orr  ip, ip, #...
+  //  orr  ip, ip, #...
+  //  orr  ip, ip, #...
+  //  ldr   ip, [pc, ip]  @ call address
+  //  blx   ip
+  //                      @ return address
   Address candidate = pc - 2 * Assembler::kInstrSize;
   Instr candidate_instr(Memory::int32_at(candidate));
   if (IsLdrPcImmediateOffset(candidate_instr) |
       IsLdrPpImmediateOffset(candidate_instr)) {
     return candidate;
-  } else if (IsLdrPpRegOffset(candidate_instr)) {
-    candidate = pc - 4 * Assembler::kInstrSize;
-    DCHECK(IsMovW(Memory::int32_at(candidate)) &&
-           IsMovT(Memory::int32_at(candidate + Assembler::kInstrSize)));
-    return candidate;
   } else {
-    candidate = pc - 3 * Assembler::kInstrSize;
-    DCHECK(IsMovW(Memory::int32_at(candidate)) &&
-           IsMovT(Memory::int32_at(candidate + kInstrSize)));
+    if (IsLdrPpRegOffset(candidate_instr)) {
+      candidate -= Assembler::kInstrSize;
+    }
+    if (CpuFeatures::IsSupported(ARMv7)) {
+      candidate -= 1 * Assembler::kInstrSize;
+      DCHECK(IsMovW(Memory::int32_at(candidate)) &&
+             IsMovT(Memory::int32_at(candidate + Assembler::kInstrSize)));
+    } else {
+      candidate -= 3 * Assembler::kInstrSize;
+      DCHECK(
+          IsMovImmed(Memory::int32_at(candidate)) &&
+          IsOrrImmed(Memory::int32_at(candidate + Assembler::kInstrSize)) &&
+          IsOrrImmed(Memory::int32_at(candidate + 2 * Assembler::kInstrSize)) &&
+          IsOrrImmed(Memory::int32_at(candidate + 3 * Assembler::kInstrSize)));
+    }
     return candidate;
   }
 }
@@ -469,14 +498,28 @@ Address Assembler::return_address_from_call_start(Address pc) {
     // Load from constant pool, small section.
     return pc + kInstrSize * 2;
   } else {
-    DCHECK(IsMovW(Memory::int32_at(pc)));
-    DCHECK(IsMovT(Memory::int32_at(pc + kInstrSize)));
-    if (IsLdrPpRegOffset(Memory::int32_at(pc + kInstrSize))) {
-      // Load from constant pool, extended section.
-      return pc + kInstrSize * 4;
+    if (CpuFeatures::IsSupported(ARMv7)) {
+      DCHECK(IsMovW(Memory::int32_at(pc)));
+      DCHECK(IsMovT(Memory::int32_at(pc + kInstrSize)));
+      if (IsLdrPpRegOffset(Memory::int32_at(pc + 2 * kInstrSize))) {
+        // Load from constant pool, extended section.
+        return pc + kInstrSize * 4;
+      } else {
+        // A movw / movt load immediate.
+        return pc + kInstrSize * 3;
+      }
     } else {
-      // A movw / movt load immediate.
-      return pc + kInstrSize * 3;
+      DCHECK(IsMovImmed(Memory::int32_at(pc)));
+      DCHECK(IsOrrImmed(Memory::int32_at(pc + kInstrSize)));
+      DCHECK(IsOrrImmed(Memory::int32_at(pc + 2 * kInstrSize)));
+      DCHECK(IsOrrImmed(Memory::int32_at(pc + 3 * kInstrSize)));
+      if (IsLdrPpRegOffset(Memory::int32_at(pc + 4 * kInstrSize))) {
+        // Load from constant pool, extended section.
+        return pc + kInstrSize * 6;
+      } else {
+        // A mov / orr load immediate.
+        return pc + kInstrSize * 5;
+      }
     }
   }
 }
@@ -493,10 +536,17 @@ void Assembler::deserialization_set_special_target_at(
 
 
 bool Assembler::is_constant_pool_load(Address pc) {
-  return !Assembler::IsMovW(Memory::int32_at(pc)) ||
-         (FLAG_enable_ool_constant_pool &&
-          Assembler::IsLdrPpRegOffset(
-              Memory::int32_at(pc + 2 * Assembler::kInstrSize)));
+  if (CpuFeatures::IsSupported(ARMv7)) {
+    return !Assembler::IsMovW(Memory::int32_at(pc)) ||
+           (FLAG_enable_ool_constant_pool &&
+            Assembler::IsLdrPpRegOffset(
+                Memory::int32_at(pc + 2 * Assembler::kInstrSize)));
+  } else {
+    return !Assembler::IsMovImmed(Memory::int32_at(pc)) ||
+           (FLAG_enable_ool_constant_pool &&
+            Assembler::IsLdrPpRegOffset(
+                Memory::int32_at(pc + 4 * Assembler::kInstrSize)));
+  }
 }
 
 
@@ -505,10 +555,22 @@ Address Assembler::constant_pool_entry_address(
   if (FLAG_enable_ool_constant_pool) {
     DCHECK(constant_pool != NULL);
     int cp_offset;
-    if (IsMovW(Memory::int32_at(pc))) {
+    if (!CpuFeatures::IsSupported(ARMv7) && IsMovImmed(Memory::int32_at(pc))) {
+      DCHECK(IsOrrImmed(Memory::int32_at(pc + kInstrSize)) &&
+             IsOrrImmed(Memory::int32_at(pc + 2 * kInstrSize)) &&
+             IsOrrImmed(Memory::int32_at(pc + 3 * kInstrSize)) &&
+             IsLdrPpRegOffset(Memory::int32_at(pc + 4 * kInstrSize)));
+      // This is an extended constant pool lookup (ARMv6).
+      Instr mov_instr = instr_at(pc);
+      Instr orr_instr_1 = instr_at(pc + kInstrSize);
+      Instr orr_instr_2 = instr_at(pc + 2 * kInstrSize);
+      Instr orr_instr_3 = instr_at(pc + 3 * kInstrSize);
+      cp_offset = DecodeShiftImm(mov_instr) | DecodeShiftImm(orr_instr_1) |
+                  DecodeShiftImm(orr_instr_2) | DecodeShiftImm(orr_instr_3);
+    } else if (IsMovW(Memory::int32_at(pc))) {
       DCHECK(IsMovT(Memory::int32_at(pc + kInstrSize)) &&
              IsLdrPpRegOffset(Memory::int32_at(pc + 2 * kInstrSize)));
-      // This is an extended constant pool lookup.
+      // This is an extended constant pool lookup (ARMv7).
       Instruction* movw_instr = Instruction::At(pc);
       Instruction* movt_instr = Instruction::At(pc + kInstrSize);
       cp_offset = (movt_instr->ImmedMovwMovtValue() << 16) |
@@ -532,8 +594,8 @@ Address Assembler::target_address_at(Address pc,
   if (is_constant_pool_load(pc)) {
     // This is a constant pool lookup. Return the value in the constant pool.
     return Memory::Address_at(constant_pool_entry_address(pc, constant_pool));
-  } else {
-    // This is an movw_movt immediate load. Return the immediate.
+  } else if (CpuFeatures::IsSupported(ARMv7)) {
+    // This is an movw / movt immediate load. Return the immediate.
     DCHECK(IsMovW(Memory::int32_at(pc)) &&
            IsMovT(Memory::int32_at(pc + kInstrSize)));
     Instruction* movw_instr = Instruction::At(pc);
@@ -541,6 +603,20 @@ Address Assembler::target_address_at(Address pc,
     return reinterpret_cast<Address>(
         (movt_instr->ImmedMovwMovtValue() << 16) |
          movw_instr->ImmedMovwMovtValue());
+  } else {
+    // This is an mov / orr immediate load. Return the immediate.
+    DCHECK(IsMovImmed(Memory::int32_at(pc)) &&
+           IsOrrImmed(Memory::int32_at(pc + kInstrSize)) &&
+           IsOrrImmed(Memory::int32_at(pc + 2 * kInstrSize)) &&
+           IsOrrImmed(Memory::int32_at(pc + 3 * kInstrSize)));
+    Instr mov_instr = instr_at(pc);
+    Instr orr_instr_1 = instr_at(pc + kInstrSize);
+    Instr orr_instr_2 = instr_at(pc + 2 * kInstrSize);
+    Instr orr_instr_3 = instr_at(pc + 3 * kInstrSize);
+    Address ret = reinterpret_cast<Address>(
+        DecodeShiftImm(mov_instr) | DecodeShiftImm(orr_instr_1) |
+        DecodeShiftImm(orr_instr_2) | DecodeShiftImm(orr_instr_3));
+    return ret;
   }
 }
 
@@ -560,9 +636,9 @@ void Assembler::set_target_address_at(Address pc,
     // ldr   ip, [pp, #...]
     // since the instruction accessing this address in the constant pool remains
     // unchanged.
-  } else {
-    // This is an movw_movt immediate load. Patch the immediate embedded in the
-    // instructions.
+  } else if (CpuFeatures::IsSupported(ARMv7)) {
+    // This is an movw / movt immediate load. Patch the immediate embedded in
+    // the instructions.
     DCHECK(IsMovW(Memory::int32_at(pc)));
     DCHECK(IsMovT(Memory::int32_at(pc + kInstrSize)));
     uint32_t* instr_ptr = reinterpret_cast<uint32_t*>(pc);
@@ -574,6 +650,26 @@ void Assembler::set_target_address_at(Address pc,
     if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
       CpuFeatures::FlushICache(pc, 2 * kInstrSize);
     }
+  } else {
+    // This is an mov / orr immediate load. Patch the immediate embedded in
+    // the instructions.
+    DCHECK(IsMovImmed(Memory::int32_at(pc)) &&
+           IsOrrImmed(Memory::int32_at(pc + kInstrSize)) &&
+           IsOrrImmed(Memory::int32_at(pc + 2 * kInstrSize)) &&
+           IsOrrImmed(Memory::int32_at(pc + 3 * kInstrSize)));
+    uint32_t* instr_ptr = reinterpret_cast<uint32_t*>(pc);
+    uint32_t immediate = reinterpret_cast<uint32_t>(target);
+    instr_ptr[0] = PatchShiftImm(instr_ptr[0], immediate & kImm8Mask);
+    instr_ptr[1] = PatchShiftImm(instr_ptr[1], immediate & (kImm8Mask << 8));
+    instr_ptr[2] = PatchShiftImm(instr_ptr[2], immediate & (kImm8Mask << 16));
+    instr_ptr[3] = PatchShiftImm(instr_ptr[3], immediate & (kImm8Mask << 24));
+    DCHECK(IsMovImmed(Memory::int32_at(pc)) &&
+           IsOrrImmed(Memory::int32_at(pc + kInstrSize)) &&
+           IsOrrImmed(Memory::int32_at(pc + 2 * kInstrSize)) &&
+           IsOrrImmed(Memory::int32_at(pc + 3 * kInstrSize)));
+    if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
+      CpuFeatures::FlushICache(pc, 4 * kInstrSize);
+    }
   }
 }