ARM: Clean up FlushICache.
authorJacob.Bramley@arm.com <Jacob.Bramley@arm.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 23 Jun 2014 17:30:00 +0000 (17:30 +0000)
committerJacob.Bramley@arm.com <Jacob.Bramley@arm.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 23 Jun 2014 17:30:00 +0000 (17:30 +0000)
In theory, the Thumb version of FlushICache doesn't have to be any
different from the ARM version: There is no need to switch to ARM mode
for the svc, and r7 can be used just like any other register.

In practice, GCC uses r7 as a frame pointer in Thumb code, and it
refuses to allow it be used in inline assembly. To avoid complicated
checks to determine whether or not it is possible to use it directly,
the FlushICache function explicitly preserves r7.

R=ulan@chromium.org

Review URL: https://codereview.chromium.org/335133002

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

src/arm/cpu-arm.cc

index 4ff82a7..78ab5f7 100644 (file)
 namespace v8 {
 namespace internal {
 
+
 void CPU::FlushICache(void* start, size_t size) {
-  // Nothing to do flushing no instructions.
-  if (size == 0) {
-    return;
-  }
+  if (size == 0) return;
 
 #if defined(USE_SIMULATOR)
   // Not generating ARM instructions for C-code. This means that we are
@@ -36,47 +34,31 @@ void CPU::FlushICache(void* start, size_t size) {
   // None of this code ends up in the snapshot so there are no issues
   // around whether or not to generate the code when building snapshots.
   Simulator::FlushICache(Isolate::Current()->simulator_i_cache(), start, size);
+
 #elif V8_OS_QNX
   msync(start, size, MS_SYNC | MS_INVALIDATE_ICACHE);
+
 #else
-  // Ideally, we would call
-  //   syscall(__ARM_NR_cacheflush, start,
-  //           reinterpret_cast<intptr_t>(start) + size, 0);
-  // however, syscall(int, ...) is not supported on all platforms, especially
-  // not when using EABI, so we call the __ARM_NR_cacheflush syscall directly.
+  register uint32_t beg asm("r0") = reinterpret_cast<uint32_t>(start);
+  register uint32_t end asm("r1") = beg + size;
+  register uint32_t flg asm("r2") = 0;
+
+  asm volatile(
+    // This assembly works for both ARM and Thumb targets.
+
+    // Preserve r7; it is callee-saved, and GCC uses it as a frame pointer for
+    // Thumb targets.
+    "  push {r7}\n"
+                                  // r0 = beg
+                                  // r1 = end
+                                  // r2 = flags (0)
+    "  ldr r7, =%[scno]\n"        // r7 = syscall number
+    "  svc 0\n"
 
-  register uint32_t beg asm("a1") = reinterpret_cast<uint32_t>(start);
-  register uint32_t end asm("a2") =
-      reinterpret_cast<uint32_t>(start) + size;
-  register uint32_t flg asm("a3") = 0;
-  #if defined (__arm__) && !defined(__thumb__)
-    // __arm__ may be defined in thumb mode.
-    register uint32_t scno asm("r7") = __ARM_NR_cacheflush;
-    asm volatile(
-        "svc 0x0"
-        : "=r" (beg)
-        : "0" (beg), "r" (end), "r" (flg), "r" (scno));
-  #else
-    // r7 is reserved by the EABI in thumb mode.
-    asm volatile(
-    "@   Enter ARM Mode  \n\t"
-        "adr r3, 1f      \n\t"
-        "bx  r3          \n\t"
-        ".ALIGN 4        \n\t"
-        ".ARM            \n"
-    "1:  push {r7}       \n\t"
-        "mov r7, %4      \n\t"
-        "svc 0x0         \n\t"
-        "pop {r7}        \n\t"
-    "@   Enter THUMB Mode\n\t"
-        "adr r3, 2f+1    \n\t"
-        "bx  r3          \n\t"
-        ".THUMB          \n"
-    "2:                  \n\t"
-        : "=r" (beg)
-        : "0" (beg), "r" (end), "r" (flg), "r" (__ARM_NR_cacheflush)
-        : "r3");
-  #endif
+    "  pop {r7}\n"
+    :
+    : "r" (beg), "r" (end), "r" (flg), [scno] "i" (__ARM_NR_cacheflush)
+    : "memory");
 #endif
 }