Fix assembly comment prefix and identify memory clobbers for AArch64
authorYvan Roux <yvan.roux@linaro.org>
Sat, 9 Mar 2013 13:00:43 +0000 (17:00 +0400)
committerIvan Maidanski <ivmai@mail.ru>
Sat, 9 Mar 2013 13:00:43 +0000 (17:00 +0400)
* src/atomic_ops/sysdeps/gcc/aarch64.h: Revert comments beginning
marker to '//' (since '@' is not supported for A64 assembler).
* src/atomic_ops/sysdeps/gcc/aarch64.h (AO_double_load): Add comment
about the need for STXP instruction; remove TODO item.
* src/atomic_ops/sysdeps/gcc/aarch64.h (AO_double_store): Add comment
about absence of "cc" in clobber lists; remove TODO item.
* src/atomic_ops/sysdeps/gcc/aarch64.h (AO_double_load,
AO_double_load_acquire, AO_double_store, AO_double_store_release,
AO_double_compare_and_swap, AO_double_compare_and_swap_acquire,
AO_double_compare_and_swap_release): Use Q constraint (instead of "r")
for 'addr' argument to instruct the compiler about memory clobbers.

src/atomic_ops/sysdeps/gcc/aarch64.h

index b4c937b..6ae26f3 100644 (file)
 /* TODO: Adjust version check on fixing double-wide AO support in GCC. */
 #if __GNUC__ == 4
 
-  /* TODO: Adjust clobber lists. */
-
   AO_INLINE AO_double_t
   AO_double_load(const volatile AO_double_t *addr)
   {
     AO_double_t result;
     int status;
 
-    /* TODO: Could we discard stxp like for 32-bit ARM? */
+    /* Note that STXP cannot be discarded because LD[A]XP is not        */
+    /* single-copy atomic (unlike LDREXD for 32-bit ARM).               */
     do {
-      __asm__ __volatile__("@AO_double_load\n"
-      "       ldxp  %0, %1, [%3]\n"
-      "       stxp %w2, %0, %1, [%3]"
+      __asm__ __volatile__("//AO_double_load\n"
+      "       ldxp  %0, %1, %3\n"
+      "       stxp %w2, %0, %1, %3"
       : "=&r" (result.AO_val1), "=&r" (result.AO_val2), "=&r" (status)
-      : "r" (addr)
-      );
+      : "Q" (*addr));
     } while (AO_EXPECT_FALSE(status));
     return result;
   }
     int status;
 
     do {
-      __asm__ __volatile__("@AO_double_load_acquire\n"
-      "       ldaxp  %0, %1, [%3]\n"
-      "       stxp %w2, %0, %1, [%3]"
+      __asm__ __volatile__("//AO_double_load_acquire\n"
+      "       ldaxp  %0, %1, %3\n"
+      "       stxp %w2, %0, %1, %3"
       : "=&r" (result.AO_val1), "=&r" (result.AO_val2), "=&r" (status)
-      : "r" (addr)
-      );
+      : "Q" (*addr));
     } while (AO_EXPECT_FALSE(status));
     return result;
   }
     int status;
 
     do {
-      __asm__ __volatile__("@AO_double_store\n"
+      __asm__ __volatile__("//AO_double_store\n"
       "       ldxp  %0, %1, %3\n"
       "       stxp %w2, %4, %5, %3"
       : "=&r" (old_val.AO_val1), "=&r" (old_val.AO_val2), "=&r" (status),
-        "+Q" (*addr)
-      : "r" (value.AO_val1), "r" (value.AO_val2)
-      );
+        "=Q" (*addr)
+      : "r" (value.AO_val1), "r" (value.AO_val2));
+      /* Compared to the arm.h implementation, the 'cc' (flags) are not */
+      /* clobbered because A64 has no concept of conditional execution. */
     } while (AO_EXPECT_FALSE(status));
   }
 # define AO_HAVE_double_store
     int status;
 
     do {
-      __asm__ __volatile__("@AO_double_store_release\n"
+      __asm__ __volatile__("//AO_double_store_release\n"
       "       ldxp  %0, %1, %3\n"
       "       stlxp %w2, %4, %5, %3"
       : "=&r" (old_val.AO_val1), "=&r" (old_val.AO_val2), "=&r" (status),
-        "+Q" (*addr)
-      : "r" (value.AO_val1), "r" (value.AO_val2)
-      );
+        "=Q" (*addr)
+      : "r" (value.AO_val1), "r" (value.AO_val2));
     } while (AO_EXPECT_FALSE(status));
   }
 # define AO_HAVE_double_store_release
     int result = 1;
 
     do {
-      __asm__ __volatile__("@AO_double_compare_and_swap\n"
-        "       ldxp  %0, %1, [%2]\n"
+      __asm__ __volatile__("//AO_double_compare_and_swap\n"
+        "       ldxp  %0, %1, %2\n"
         : "=&r" (tmp.AO_val1), "=&r" (tmp.AO_val2)
-        : "r" (addr)
-        );
+        : "Q" (*addr));
       if (tmp.AO_val1 != old_val.AO_val1 || tmp.AO_val2 != old_val.AO_val2)
         break;
       __asm__ __volatile__(
         "       stxp %w0, %2, %3, %1\n"
-        : "=&r" (result), "+Q" (*addr)
-        : "r" (new_val.AO_val1), "r" (new_val.AO_val2), "r" (addr)
-      );
+        : "=&r" (result), "=Q" (*addr)
+        : "r" (new_val.AO_val1), "r" (new_val.AO_val2));
     } while (AO_EXPECT_FALSE(result));
     return !result;
   }
 
   AO_INLINE int
   AO_double_compare_and_swap_acquire(volatile AO_double_t *addr,
-                             AO_double_t old_val, AO_double_t new_val)
+                                     AO_double_t old_val, AO_double_t new_val)
   {
     AO_double_t tmp;
     int result = 1;
 
     do {
-      __asm__ __volatile__("@AO_double_compare_and_swap_acquire\n"
-        "       ldaxp  %0, %1, [%2]\n"
+      __asm__ __volatile__("//AO_double_compare_and_swap_acquire\n"
+        "       ldaxp  %0, %1, %2\n"
         : "=&r" (tmp.AO_val1), "=&r" (tmp.AO_val2)
-        : "r" (addr)
-        );
+        : "Q" (*addr));
       if (tmp.AO_val1 != old_val.AO_val1 || tmp.AO_val2 != old_val.AO_val2)
         break;
       __asm__ __volatile__(
         "       stxp %w0, %2, %3, %1\n"
-        : "=&r" (result), "+Q" (*addr)
-        : "r" (new_val.AO_val1), "r" (new_val.AO_val2), "r" (addr)
-      );
+        : "=&r" (result), "=Q" (*addr)
+        : "r" (new_val.AO_val1), "r" (new_val.AO_val2));
     } while (AO_EXPECT_FALSE(result));
     return !result;
   }
 
   AO_INLINE int
   AO_double_compare_and_swap_release(volatile AO_double_t *addr,
-                             AO_double_t old_val, AO_double_t new_val)
+                                     AO_double_t old_val, AO_double_t new_val)
   {
     AO_double_t tmp;
     int result = 1;
 
     do {
-      __asm__ __volatile__("@AO_double_compare_and_swap_release\n"
-        "       ldxp  %0, %1, [%2]\n"
+      __asm__ __volatile__("//AO_double_compare_and_swap_release\n"
+        "       ldxp  %0, %1, %2\n"
         : "=&r" (tmp.AO_val1), "=&r" (tmp.AO_val2)
-        : "r" (addr)
-        );
+        : "Q" (*addr));
       if (tmp.AO_val1 != old_val.AO_val1 || tmp.AO_val2 != old_val.AO_val2)
         break;
       __asm__ __volatile__(
         "       stlxp %w0, %2, %3, %1\n"
-        : "=&r" (result), "+Q" (*addr)
-        : "r" (new_val.AO_val1), "r" (new_val.AO_val2), "r" (addr)
-      );
+        : "=&r" (result), "=Q" (*addr)
+        : "r" (new_val.AO_val1), "r" (new_val.AO_val2));
     } while (AO_EXPECT_FALSE(result));
     return !result;
   }