summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorYvan Roux <yvan.roux@linaro.org>2013-03-09 17:00:43 +0400
committerIvan Maidanski <ivmai@mail.ru>2013-03-09 17:00:43 +0400
commit5d6e9433c5edd91e21919536ea4a1ea6bb940122 (patch)
tree63fa6d669fa0ddfdc32d9624e5ea2d1fb8ff54fa /src
parent1ce472e50783c92a0b4c0d8b966bd7cc04f4cbe5 (diff)
downloadlibatomic_ops-5d6e9433c5edd91e21919536ea4a1ea6bb940122.tar.gz
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.
Diffstat (limited to 'src')
-rw-r--r--src/atomic_ops/sysdeps/gcc/aarch64.h79
1 files 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;
}