]> granicus.if.org Git - libatomic_ops/commitdiff
Initial ibmc/powerpc (xlc) support
authorFabrizio Fabbri <ffabbri4@bloomberg.net>
Wed, 2 Mar 2016 16:35:47 +0000 (11:35 -0500)
committerIvan Maidanski <ivmai@mail.ru>
Fri, 4 Mar 2016 18:10:59 +0000 (21:10 +0300)
* src/atomic_ops/sysdeps/ibmc/powerpc.h: Include
test_and_set_t_is_ao_t.h.
* src/atomic_ops/sysdeps/ibmc/powerpc.h (AO_test_and_set,
AO_fetch_compare_and_swap): Implement.

src/atomic_ops/sysdeps/ibmc/powerpc.h

index e2d40272aa7d08eb701e07a46aef5de2f8c92a42..a930b16794d0fc1c3f36d1d9cbe2c011bfba3260 100644 (file)
@@ -1,5 +1,4 @@
-/* FIXME.  This is only a placeholder for the AIX compiler.             */
-/* It doesn't work.  Please send a patch.                               */
+
 /* Memory model documented at http://www-106.ibm.com/developerworks/    */
 /* eserver/articles/archguide.html and (clearer)                        */
 /* http://www-106.ibm.com/developerworks/eserver/articles/powerpc.html. */
@@ -16,6 +15,8 @@
 
 #include "../all_aligned_atomic_load_store.h"
 
+#include "../test_and_set_t_is_ao_t.h"
+
 void AO_sync(void);
 #pragma mc_func AO_sync { "7c0004ac" }
 
@@ -55,11 +56,41 @@ AO_store_release(volatile AO_t *addr, AO_t value)
 /* This is similar to the code in the garbage collector.  Deleting      */
 /* this and having it synthesized from compare_and_swap would probably  */
 /* only cost us a load immediate instruction.                           */
-/*AO_INLINE AO_TS_VAL_t
+AO_INLINE AO_TS_VAL_t
 AO_test_and_set(volatile AO_TS_t *addr) {
-# error FIXME Implement me
+#if defined(__powerpc64__) || defined(__ppc64__) || defined(__64BIT__)
+/* Completely untested.  And we should be using smaller objects anyway. */
+  unsigned long oldval;
+  unsigned long temp = 1; /* locked value */
+
+  __asm__ __volatile__(
+               "1:ldarx %0,0,%1\n"   /* load and reserve               */
+               "cmpdi %0, 0\n"       /* if load is                     */
+               "bne 2f\n"            /*   non-zero, return already set */
+               "stdcx. %2,0,%1\n"    /* else store conditional         */
+               "bne- 1b\n"           /* retry if lost reservation      */
+               "2:\n"                /* oldval is zero if we set       */
+              : "=&r"(oldval)
+              : "r"(addr), "r"(temp)
+              : "memory", "cr0");
+#else
+  int oldval;
+  int temp = 1; /* locked value */
+
+  __asm__ __volatile__(
+               "1:lwarx %0,0,%1\n"   /* load and reserve               */
+               "cmpwi %0, 0\n"       /* if load is                     */
+               "bne 2f\n"            /*   non-zero, return already set */
+               "stwcx. %2,0,%1\n"    /* else store conditional         */
+               "bne- 1b\n"           /* retry if lost reservation      */
+               "2:\n"                /* oldval is zero if we set       */
+              : "=&r"(oldval)
+              : "r"(addr), "r"(temp)
+              : "memory", "cr0");
+#endif
+  return (AO_TS_VAL_t)oldval;
 }
-#define AO_HAVE_test_and_set*/
+#define AO_HAVE_test_and_set
 
 AO_INLINE AO_TS_VAL_t
 AO_test_and_set_acquire(volatile AO_TS_t *addr) {
@@ -87,12 +118,36 @@ AO_test_and_set_full(volatile AO_TS_t *addr) {
 #define AO_HAVE_test_and_set_full
 #endif /* !AO_PREFER_GENERALIZED */
 
-/*AO_INLINE AO_t
+AO_INLINE AO_t
 AO_fetch_compare_and_swap(volatile AO_t *addr, AO_t old_val, AO_t new_val)
 {
-# error FIXME Implement me
+  AO_t fetched_val;
+# if defined(__powerpc64__) || defined(__ppc64__) || defined(__64BIT__)
+    __asm__ __volatile__(
+      "1:ldarx %0,0,%1\n"       /* load and reserve             */
+      "cmpd %0, %3\n"           /* if load is not equal to      */
+      "bne 2f\n"                /*   old_val, fail              */
+      "stdcx. %2,0,%1\n"        /* else store conditional       */
+      "bne- 1b\n"               /* retry if lost reservation    */
+      "2:\n"
+      : "=&r"(fetched_val)
+      : "r"(addr), "r"(new_val), "r"(old_val)
+      : "memory", "cr0");
+# else
+    __asm__ __volatile__(
+      "1:lwarx %0,0,%1\n"       /* load and reserve             */
+      "cmpw %0, %3\n"           /* if load is not equal to      */
+      "bne 2f\n"                /*   old_val, fail              */
+      "stwcx. %2,0,%1\n"        /* else store conditional       */
+      "bne- 1b\n"               /* retry if lost reservation    */
+      "2:\n"
+      : "=&r"(fetched_val)
+      : "r"(addr), "r"(new_val), "r"(old_val)
+      : "memory", "cr0");
+# endif
+  return fetched_val;
 }
-#define AO_HAVE_fetch_compare_and_swap*/
+#define AO_HAVE_fetch_compare_and_swap
 
 AO_INLINE AO_t
 AO_fetch_compare_and_swap_acquire(volatile AO_t *addr, AO_t old_val,