Implement AO_double_load for gcc/arm
authorIvan Maidanski <ivmai@mail.ru>
Sun, 6 Jan 2013 11:03:56 +0000 (15:03 +0400)
committerIvan Maidanski <ivmai@mail.ru>
Sun, 6 Jan 2013 11:03:56 +0000 (15:03 +0400)
* src/atomic_ops/sysdeps/armcc/arm_v6.h (AO_load_ex): Add 'const'
qualifier to argument pointer type.
* src/atomic_ops/sysdeps/gcc/arm.h (AO_fetch_and_add,
AO_fetch_and_add1, AO_fetch_and_sub1, AO_compare_and_swap): Remove
useless comment.
* src/atomic_ops/sysdeps/gcc/arm.h (AO_double_load): Implement (only
for ARMv7+).
* src/atomic_ops/sysdeps/armcc/arm_v6.h (AO_double_load): Likewise.

src/atomic_ops/sysdeps/armcc/arm_v6.h
src/atomic_ops/sysdeps/gcc/arm.h

index fad43fc..4c965b1 100644 (file)
@@ -221,7 +221,7 @@ __asm__ {
 /* helper functions for the Realview compiler: LDREXD is not usable
  * with inline assembler, so use the "embedded" assembler as
  * suggested by ARM Dev. support (June 2008). */
-__asm inline double_ptr_storage AO_load_ex(volatile AO_double_t *addr) {
+__asm inline double_ptr_storage AO_load_ex(const volatile AO_double_t *addr) {
         LDREXD r0,r1,[r0]
 }
 
@@ -230,6 +230,16 @@ __asm inline int AO_store_ex(AO_t val1, AO_t val2, volatile AO_double_t *addr) {
         MOV    r0,r3
 }
 
+AO_INLINE AO_double_t
+AO_double_load(const volatile AO_double_t *addr)
+{
+  AO_double_t result;
+
+  result.AO_whole = AO_load_ex(addr);
+  return result;
+}
+#define AO_HAVE_double_load
+
 AO_INLINE int
 AO_compare_double_and_swap_double(volatile AO_double_t *addr,
                                   AO_t old_val1, AO_t old_val2,
index 324f4a5..62de090 100644 (file)
@@ -193,7 +193,6 @@ AO_INLINE void AO_store(volatile AO_t *addr, AO_t value)
 # define AO_HAVE_test_and_set
 #endif /* !AO_FORCE_USE_SWP */
 
-/* NEC LE-IT: fetch and add for ARMv6 */
 AO_INLINE AO_t
 AO_fetch_and_add(volatile AO_t *p, AO_t incr)
 {
@@ -215,7 +214,6 @@ AO_fetch_and_add(volatile AO_t *p, AO_t incr)
 }
 #define AO_HAVE_fetch_and_add
 
-/* NEC LE-IT: fetch and add1 for ARMv6 */
 AO_INLINE AO_t
 AO_fetch_and_add1(volatile AO_t *p)
 {
@@ -237,7 +235,6 @@ AO_fetch_and_add1(volatile AO_t *p)
 }
 #define AO_HAVE_fetch_and_add1
 
-/* NEC LE-IT: fetch and sub for ARMv6 */
 AO_INLINE AO_t
 AO_fetch_and_sub1(volatile AO_t *p)
 {
@@ -260,7 +257,6 @@ AO_fetch_and_sub1(volatile AO_t *p)
 #define AO_HAVE_fetch_and_sub1
 #endif /* !AO_PREFER_GENERALIZED */
 
-/* NEC LE-IT: compare and swap */
 #ifndef AO_GENERALIZE_ASM_BOOL_CAS
   /* Returns nonzero if the comparison succeeded.       */
   AO_INLINE int
@@ -315,6 +311,20 @@ AO_fetch_compare_and_swap(volatile AO_t *addr, AO_t old_val, AO_t new_val)
 #ifdef AO_ARM_HAVE_LDREXD
 # include "../standard_ao_double_t.h"
 
+  AO_INLINE AO_double_t
+  AO_double_load(const volatile AO_double_t *addr)
+  {
+    AO_double_t result;
+
+    __asm__ __volatile__("@AO_double_load\n"
+      "       ldrexd  %0, [%1]"
+      : "=&r" (result.AO_whole)
+      : "r" (addr)
+      /* : no clobber */);
+    return result;
+  }
+# define AO_HAVE_double_load
+
   AO_INLINE int
   AO_double_compare_and_swap(volatile AO_double_t *addr,
                              AO_double_t old_val, AO_double_t new_val)