From 8565270c0e35dd80c10e20a57f4c89655eaa09ad Mon Sep 17 00:00:00 2001 From: Frank Schaefer Date: Tue, 23 Oct 2018 22:11:02 -0500 Subject: [PATCH] Support ILP32 in AArch64 assembly routines (GCC) (back-port of commit 3f41ecb from 'release-7_6') Issue #38 (libatomic_ops). * src/atomic_ops/sysdeps/gcc/aarch64.h [(!__clang__ || AO_AARCH64_ASM_LOAD_STORE_CAS) && !AO_PREFER_GENERALIZED && __ILP32__] (AO_double_load, AO_double_load_acquire, AO_double_store, AO_double_store_release): Specify the size ("w") of arguments of the aarch64 instructions. * src/atomic_ops/sysdeps/gcc/aarch64.h [(!__clang__ || AO_AARCH64_ASM_LOAD_STORE_CAS) && __ILP32__] (AO_double_compare_and_swap, AO_double_compare_and_swap_acquire, AO_double_compare_and_swap_release, AO_double_compare_and_swap_full): Likewise. * src/atomic_ops/sysdeps/standard_ao_double_t.h [__aarch64__ && __ILP32__] (double_ptr_storage): Define as unsigned long long (instead of unsigned __int128). --- src/atomic_ops/sysdeps/gcc/aarch64.h | 84 ++++++++++++++++++++++----- src/atomic_ops/sysdeps/standard_ao_double_t.h | 2 +- 2 files changed, 69 insertions(+), 17 deletions(-) diff --git a/src/atomic_ops/sysdeps/gcc/aarch64.h b/src/atomic_ops/sysdeps/gcc/aarch64.h index b9624ef..6db47fb 100644 --- a/src/atomic_ops/sysdeps/gcc/aarch64.h +++ b/src/atomic_ops/sysdeps/gcc/aarch64.h @@ -41,8 +41,13 @@ /* 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" +# ifdef __ILP32__ + " ldxp %w0, %w1, %3\n" + " stxp %w2, %w0, %w1, %3" +# else + " ldxp %0, %1, %3\n" + " stxp %w2, %0, %1, %3" +# endif : "=&r" (result.AO_val1), "=&r" (result.AO_val2), "=&r" (status) : "Q" (*addr)); } while (AO_EXPECT_FALSE(status)); @@ -58,8 +63,13 @@ do { __asm__ __volatile__("//AO_double_load_acquire\n" - " ldaxp %0, %1, %3\n" - " stxp %w2, %0, %1, %3" +# ifdef __ILP32__ + " ldaxp %w0, %w1, %3\n" + " stxp %w2, %w0, %w1, %3" +# else + " ldaxp %0, %1, %3\n" + " stxp %w2, %0, %1, %3" +# endif : "=&r" (result.AO_val1), "=&r" (result.AO_val2), "=&r" (status) : "Q" (*addr)); } while (AO_EXPECT_FALSE(status)); @@ -75,8 +85,13 @@ do { __asm__ __volatile__("//AO_double_store\n" - " ldxp %0, %1, %3\n" - " stxp %w2, %4, %5, %3" +# ifdef __ILP32__ + " ldxp %w0, %w1, %3\n" + " stxp %w2, %w4, %w5, %3" +# else + " ldxp %0, %1, %3\n" + " stxp %w2, %4, %5, %3" +# endif : "=&r" (old_val.AO_val1), "=&r" (old_val.AO_val2), "=&r" (status), "=Q" (*addr) : "r" (value.AO_val1), "r" (value.AO_val2)); @@ -94,8 +109,13 @@ do { __asm__ __volatile__("//AO_double_store_release\n" - " ldxp %0, %1, %3\n" - " stlxp %w2, %4, %5, %3" +# ifdef __ILP32__ + " ldxp %w0, %w1, %3\n" + " stlxp %w2, %w4, %w5, %3" +# else + " ldxp %0, %1, %3\n" + " stlxp %w2, %4, %5, %3" +# endif : "=&r" (old_val.AO_val1), "=&r" (old_val.AO_val2), "=&r" (status), "=Q" (*addr) : "r" (value.AO_val1), "r" (value.AO_val2)); @@ -112,13 +132,21 @@ do { __asm__ __volatile__("//AO_double_compare_and_swap\n" - " ldxp %0, %1, %2\n" +# ifdef __ILP32__ + " ldxp %w0, %w1, %2\n" +# else + " ldxp %0, %1, %2\n" +# endif : "=&r" (tmp.AO_val1), "=&r" (tmp.AO_val2) : "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" +# ifdef __ILP32__ + " stxp %w0, %w2, %w3, %1\n" +# else + " stxp %w0, %2, %3, %1\n" +# endif : "=&r" (result), "=Q" (*addr) : "r" (new_val.AO_val1), "r" (new_val.AO_val2)); } while (AO_EXPECT_FALSE(result)); @@ -135,13 +163,21 @@ do { __asm__ __volatile__("//AO_double_compare_and_swap_acquire\n" - " ldaxp %0, %1, %2\n" +# ifdef __ILP32__ + " ldaxp %w0, %w1, %2\n" +# else + " ldaxp %0, %1, %2\n" +# endif : "=&r" (tmp.AO_val1), "=&r" (tmp.AO_val2) : "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" +# ifdef __ILP32__ + " stxp %w0, %w2, %w3, %1\n" +# else + " stxp %w0, %2, %3, %1\n" +# endif : "=&r" (result), "=Q" (*addr) : "r" (new_val.AO_val1), "r" (new_val.AO_val2)); } while (AO_EXPECT_FALSE(result)); @@ -158,13 +194,21 @@ do { __asm__ __volatile__("//AO_double_compare_and_swap_release\n" - " ldxp %0, %1, %2\n" +# ifdef __ILP32__ + " ldxp %w0, %w1, %2\n" +# else + " ldxp %0, %1, %2\n" +# endif : "=&r" (tmp.AO_val1), "=&r" (tmp.AO_val2) : "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" +# ifdef __ILP32__ + " stlxp %w0, %w2, %w3, %1\n" +# else + " stlxp %w0, %2, %3, %1\n" +# endif : "=&r" (result), "=Q" (*addr) : "r" (new_val.AO_val1), "r" (new_val.AO_val2)); } while (AO_EXPECT_FALSE(result)); @@ -181,13 +225,21 @@ do { __asm__ __volatile__("//AO_double_compare_and_swap_full\n" - " ldaxp %0, %1, %2\n" +# ifdef __ILP32__ + " ldaxp %w0, %w1, %2\n" +# else + " ldaxp %0, %1, %2\n" +# endif : "=&r" (tmp.AO_val1), "=&r" (tmp.AO_val2) : "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" +# ifdef __ILP32__ + " stlxp %w0, %w2, %w3, %1\n" +# else + " stlxp %w0, %2, %3, %1\n" +# endif : "=&r" (result), "=Q" (*addr) : "r" (new_val.AO_val1), "r" (new_val.AO_val2)); } while (AO_EXPECT_FALSE(result)); diff --git a/src/atomic_ops/sysdeps/standard_ao_double_t.h b/src/atomic_ops/sysdeps/standard_ao_double_t.h index 2a676ea..fd0dd6e 100644 --- a/src/atomic_ops/sysdeps/standard_ao_double_t.h +++ b/src/atomic_ops/sysdeps/standard_ao_double_t.h @@ -32,7 +32,7 @@ typedef __m128 double_ptr_storage; #elif defined(_WIN32) && !defined(__GNUC__) typedef unsigned __int64 double_ptr_storage; -#elif defined(__aarch64__) +#elif defined(__aarch64__) && !defined(__ILP32__) typedef unsigned __int128 double_ptr_storage; #elif defined(__i386__) && defined(__GNUC__) typedef unsigned long long double_ptr_storage -- 2.7.4