From 5d6e9433c5edd91e21919536ea4a1ea6bb940122 Mon Sep 17 00:00:00 2001 From: Yvan Roux Date: Sat, 9 Mar 2013 17:00:43 +0400 Subject: [PATCH] Fix assembly comment prefix and identify memory clobbers for AArch64 * 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 | 79 ++++++++++++---------------- 1 file changed, 35 insertions(+), 44 deletions(-) diff --git a/src/atomic_ops/sysdeps/gcc/aarch64.h b/src/atomic_ops/sysdeps/gcc/aarch64.h index b4c937b..6ae26f3 100644 --- a/src/atomic_ops/sysdeps/gcc/aarch64.h +++ b/src/atomic_ops/sysdeps/gcc/aarch64.h @@ -31,22 +31,20 @@ /* 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; } @@ -59,12 +57,11 @@ 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; } @@ -77,13 +74,14 @@ 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 @@ -95,13 +93,12 @@ 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 @@ -114,18 +111,16 @@ 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; } @@ -133,24 +128,22 @@ 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; } @@ -158,24 +151,22 @@ 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; } -- 2.40.0